/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uns.fit.gis.mapdrawer;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.Vector;

import javax.bluetooth.RemoteDevice;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;

import org.qcontinuum.astro.EarthPosition;

import uns.fit.gis.MapDrawer;
import uns.fit.gis.NokiaKeyDef;
import uns.fit.gis.Util;
import uns.fit.gis.VietnameseConverter;
import uns.fit.gis.alg.RouteTrackingThread;
import uns.fit.gis.alg.RoutingAlgorithm;
import uns.fit.gis.alg.RoutingAlgorithm2;
import uns.fit.gis.contextmenu.BestRouteContextMenu;
import uns.fit.gis.contextmenu.ContextMenu;
import uns.fit.gis.contextmenu.GPSContextMenu;
import uns.fit.gis.contextmenu.GlobalContextMenu;
import uns.fit.gis.contextmenu.SearchLocationContextMenu;
import uns.fit.gis.contextmenu.SearchPathContextMenu;
import uns.fit.gis.gps.Gps;
import uns.fit.gis.gps.MobileGPS;
import uns.fit.gis.httpconnection.MHttpConnItem;
import uns.fit.gis.httpconnection.MHttpConnection;
import uns.fit.gis.httpconnection.MHttpConnectionHandler;
import uns.fit.gis.mapio.MapReader;
import uns.fit.gis.mapobj.Crossroads;
import uns.fit.gis.mapobj.Path;
import uns.fit.gis.mapobj.Point;
import uns.fit.gis.mapobj.Region;
import uns.fit.gis.mapobj.Segment;
import uns.fit.gis.mapobj.SimpleLocation;
import uns.fit.gis.qwarper.QWarper;
import uns.fit.gis.qwarper.Quad;
import uns.fit.gis.rms.RSManager;
import uns.fit.gis.serviceapp.Connector;
import uns.fit.gis.serviceapp.Service1Soap_Stub;
import uns.fit.gis.ui.LayerList;
import uns.fit.gis.ui.SearchPathForm;

/**
 * @author Nguyen Le
 * Y TUONG:
 * - Luu mang object thanh mang primary (int, byte, ...).
 * - Lam pie menu (lam context menu / pop-up menu).
 * - Xay dung cac Graphics pool, Data pool, ...
 * de chua cac doi tuong graphics va data dung chung.
 * - Trong bang lo trinh ngan nhat, chon doan nao thi hien doan do len ban do, nhan 0 de chuyen doan.
 *
 * VAN DE:
 * - Tim duong ma khong Xoa ket qua thi sai: FIXED.
 * - Tim duong tam on, nhung ve sai: FIXED.
 * - Bi tran bo nho khi tim duong theo ten: FIXED so so.
 * - DRIVING ASSISTANT: canh lai vi tri xe. FIX gan xong bang cach cho ban do xoay quanh vi tri hien tai.
 * Van con loi ve (mat 1 doan segment), do clipping. Co the khac phuc bang cach cho hinh chu nhat chieu lon hon man hinh???
 * Mo rong vung ve --> Tam on
 * - Chuyen phan xoay (trong ve duong) vao drawLine3D: khong duoc, vi toa do da bi clipping, xoay se bi thieu
 * - Xoay trong ve lo trinh: FIXED
 * - Lo cot: lap ds segment bi cam (do lo cot) bang cach duyet cac lo cot va tim segment gan nhat --> OK
 * - Loi khi tim duong bang Dijkstra (sau khi xoa lo trinh thi ve lo trinh moi sai --> Dem phan tinh toan truoc khi ve vao RoutingAlgorithm
 */
public class MapCanvas extends Canvas implements CommandListener, MHttpConnectionHandler {

    /**
     * constructor
     */
    //private final int INSET_X = 30;
    //private final int INSET_Y = 80;
    private final int INSET_X = 0;
    private final int INSET_Y = 0;
    private final int EXTRA_LOWER_EDGE = 300;
    private final int EPSILON = 5;
    private int DX = 80;
    private int DY = 80;
    private int CURSOR_STEP = 10;
    public static final int MIN_X = 0; // Minimum X of Map
    public static final int MIN_Y = 0; // Minimum Y of Map
    public static final int MAX_X = 65534; // Maximum X of Map
    public static final int MAX_Y = 65508; // Maximum Y of Map
    public static final int MAX_TRACK_POINTS = 30;

    /*
    private int MinX = 0; // Minimum X of Map
    private int MinY = 0; // Minimum Y of Map

    private int MaxX = 65534; // Maximum X of Map
    private int MaxY = 65508; // Maximum Y of Map
     */
    public static int MinX = 41000; // Minimum X of Map (visible on Screen)
    public static int MinY = 46000; // Minimum Y of Map (visible on Screen)
    public static int MaxX = MinX + 300; // Maximum X of Map (visible on Screen)
    public static int MaxY = MinY + 300; // Maximum Y of Map (visible on Screen)
    public ContextMenu contextMenu;
    /*
    private Command exitCommand;
    private Command gpsCommand;
    private Command menuCommand;
    private Command searchPathCommand;
    private Command viewRoutesCommand;
    private Command setDestinationPointCommand;
    private Command clearBestRouteCommand;
    private Command test;
    private Command cameraCommand;
    private Command recorderCommand;
    private Command locationCommand;
    private Command viewBestRouteCommand;
    private Command drivingAssistCommand;
     */
    private MapDrawer midlet;
    public static Segment[] segments;
    public static Path[] paths;
    public static Region[] regions;
    public static SimpleLocation[] locations;
    public static Crossroads[] cross;
    public static Vector constructionSiteSegmentIds;
    public static Vector userLocations;
    private MapReader mapReader;
    public static int screenWidth = 240;
    public static int screenHeight = 320;
    public static int screenWidthDiv2 = 120;
    public static int screenHeightDiv2 = 160;
    public static Image imageMap;
    private Graphics bkgGraphics;
    private Image alphabet;
    private Image alphabet90;
    private Image arrow;
    private Sprite cursor;
    private Sprite pointer;
    private String placeNearCursor;
    private Sprite placeSprite;
    private Sprite routeSprite;
    private Sprite compassSprite;
    private StringDrawer stringDrawer;
    private ArrowDrawer arrowDrawer;
    private Timer myTime = new Timer();
    private Service1Soap_Stub service;
    public static boolean drawArc = false;
//    private String imei = "";
//    private String cellid = "";
    private Segment[] location = new Segment[3];
//    private Calendar c;
//    private String time;
    /*
     * For GPS
     */
    public static Vector track;
    public static boolean drawTrack = false;
    public static EarthPosition earthPosition;
    public static boolean stopGPSThread;
    public static boolean moveToCurrentPosition;
    public static boolean assistDriving;
    private byte zoomLevel; // 1 --> 5
    private boolean is3D;
    private byte numSegmentTypes = 8; // 0 --> 7
    private byte[] segmentWidths = {
        1, 1, 0, 0, 0, 0, 0, 0,
        2, 2, 1, 0, 0, 0, 0, 0,
        3, 3, 2, 1, 0, 0, 0, 0,
        6, 6, 3, 2, 0, 0, 0, 0,
        8, 8, 6, 3, 1, 0, 0, 1,
        8, 8, 8, 6, 3, 0, 0, 2
    };
    private Sprite vanSprite;
    private Quad sourceQuad;
    private Quad destQuad;
    private QWarper warper;
    public static int currentX;
    public static int currentY;
    public static int cursorCenterX;
    public static int cursorCenterY;
    public static Point currentPositionOnScreen;

    /*
     * Rotation
     */
    private int rotationAngle;

    /*
     * Finding shortest route
     */
    public static RoutingAlgorithm alg;
    public static RoutingAlgorithm2 alg2;
    private Font font;

    public MapCanvas(MapDrawer midlet) {
        try {
            //c = Calendar.getInstance();
            /*
            Metadata metadata = JpegMetadataReader.readMetadata(this.getClass()
            .getResourceAsStream("/withIptcExifGps.jpg"));
            ExifDirectory directory = (ExifDirectory)metadata.getDirectory(ExifDirectory.class);

            Vector tags = directory.getTagIterator();
            System.out.println("tag iterator obtained! tag count, "+ directory.getTagCount()+" size: "+tags.size());
            for (int y=0; y<tags.size(); y++) {
            Tag tag = (Tag)tags.elementAt(y);
            System.out.println(tag);
            }
             */

            this.midlet = midlet;
            // Set up this canvas to listen to command events
            setCommandListener(this);
            // Add the commands
            contextMenu = new GlobalContextMenu();
            contextMenu.attach(this);

            screenHeight = getHeight();
            screenWidth = getWidth();
            screenWidthDiv2 = screenWidth / 2;
            screenHeightDiv2 = screenHeight / 2;

            track = new Vector();

            alphabet = Image.createImage("/abc.png");
            alphabet90 = Image.createImage("/abc90.png");
            arrow = Image.createImage("/arrow.png");
            cursor = new Sprite(Image.createImage("/cursor.png"));
            cursor.setPosition(screenWidthDiv2, screenHeightDiv2);
            pointer = new Sprite(Image.createImage("/pointer.png"));
            routeSprite = new Sprite(Image.createImage("/placeicon.png"), 16, 21);
            vanSprite = new Sprite(Image.createImage("/van.png"), 18, 18);
            vanSprite.setFrame(1);

            placeNearCursor = null;
            placeSprite = new Sprite(Image.createImage("/place.png"), 16, 16);
            compassSprite = new Sprite(Image.createImage("/compass.png"), 32, 32);
            compassSprite.setPosition(screenWidth - 40, 8);
            compassSprite.defineReferencePixel(16, 16);
            compassSprite.setFrame(0);

            stringDrawer = new StringDrawer(alphabet, alphabet90);
            arrowDrawer = new ArrowDrawer(arrow);
            //cursorDrawer = new CursorDrawer(cursor);

            cursorCenterX = MinX + 150;
            cursorCenterY = MinY + 150;
            stopGPSThread = true;
            moveToCurrentPosition = true;
            assistDriving = false;
            zoomLevel = 5;
            is3D = false;

            sourceQuad = new Quad(0, 0,
                    screenWidth, 0,
                    screenWidth, screenHeight,
                    0, screenHeight);
            destQuad = new Quad(INSET_X, INSET_Y,
                    screenWidth - INSET_X, INSET_Y,
                    screenWidth + EXTRA_LOWER_EDGE, screenHeight,
                    -EXTRA_LOWER_EDGE, screenHeight);

            //quadMap = new QuadMap(sourceQuad, destQuad);
            warper = new QWarper(destQuad, sourceQuad, true);

            //route = null;

            imageMap = Image.createImage(screenWidth, screenHeight);
            bkgGraphics = imageMap.getGraphics();

            rotationAngle = 0;

            font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
            bkgGraphics.setFont(font);


            mapReader = new MapReader();

            paths = mapReader.readPathsFromBinaryFile("/path");
            segments = mapReader.segments;
            regions = mapReader.readPolygonsFromBinaryFile("/region");
            locations = mapReader.readPOIsFromBinaryFile("/place");
            cross = mapReader.readCrossroadsesFromBinaryFile("/cross");
            constructionSiteSegmentIds = mapReader.readConstructionSites("/locot");
            /*
             * Load user's locations
             */
            /*
            new Thread() {
            public void run() {
            userLocations = FileWrapper.loadUserLocations(Util.STORAGE_FOLDER + Util.USER_LOCATION_FILE_NAME);
            }
            }.start();
            Thread.sleep(5000);
             */
            RSManager.open(Util.USER_LOCATION_RECORDSTORE_NAME);
            userLocations = RSManager.loadUserLocations();
            RSManager.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.gc();
    }

    public boolean shouldRenderLine(int x0, int y0, int x1, int y1) {
        int minX = x0;
        int maxX = x1;
        if (x0 > x1) {
            minX = x1;
            maxX = x0;
        }
        int minY = y0;
        int maxY = y1;
        if (y0 > y1) {
            minY = y1;
            maxY = y0;
        }
        return Util.isIntersecting(minX, minY, maxX, maxY);
    }

    private void drawRect(Graphics g, int x0, int y0, int x1, int y1) {
        x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
        y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
        x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
        y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

        g.drawRect(x0, x0, x1 - x0, y1 - y0);
    }
    /*
     * paint
     * (non-Javadoc)
     * @see javax.microedition.lcdui.Canvas#paint(javax.microedition.lcdui.Graphics)
     */

    public void paint(Graphics g) {
        if (is3D && !stopGPSThread) {
            System.out.println("ANGLE = " + rotationAngle);
            currentPositionOnScreen = new Point(getXMap2Screen(currentX), getYMap2Screen(currentY));
        }

        long before = System.currentTimeMillis();
        if (bkgGraphics != null) {
            placeNearCursor = null;
            cursorCenterX = getXScreen2Map(cursor.getX() + 10);
            cursorCenterY = getYScreen2Map(cursor.getY() + 10);

            bkgGraphics.setColor(221, 238, 187);
            //bkgGraphics.setColor(102, 205, 170); // medium aquamarine
            //bkgGraphics.setColor(143, 188, 143); // dark sea green
            //bkgGraphics.setColor(205, 201, 165); // lemonchiffon 3
            //bkgGraphics.setColor(154, 205, 50); // yellow green

            bkgGraphics.fillRect(0, 0, screenWidth, screenHeight);

            /*
             * Only draw when zoomLevel = 3 --> 5
             * Type is not exactly, so only set one color
             */

            if (zoomLevel > 2) {
                //System.out.println("REGIONS: " + regions.length);
                //bkgGraphics.setColor(240, 255, 240); // Honeydew
                bkgGraphics.setColor(102, 205, 170);	// Aquamarine3
                for (int i = 0; i < regions.length; i++) {
                    int maxX = regions[i].getMaxX();
                    int maxY = regions[i].getMaxY();
                    int minX = regions[i].getMinX();
                    int minY = regions[i].getMinY();
                    // drawRect(g, minX, minY, maxX, maxY);
                    if (Util.isIntersecting(minX, minY, maxX, maxY)) {
                        drawRegion(bkgGraphics, regions[i]);
                        if (Util.isInside(cursorCenterX, cursorCenterY, minX, minY, maxX, maxY)) {
                            if (regions[i].getName() != null) {
                                if (regions[i].getName().length > 0) {
                                    placeNearCursor = Util.decodeCharacters(regions[i].getName());
                                }
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < segments.length; i++) {
                Segment segment = segments[i];
                int maxX = segment.getMaxX();
                int maxY = segment.getMaxY();
                int minX = segment.getMinX();
                int minY = segment.getMinY();
                // If MBR of segment intersects with VIEW,
                // draw it
                if (Util.isIntersecting(minX, minY, maxX, maxY)) {
                    /*
                     * System.out.println("MinX = " + minX);
                     * System.out.println("MaxX = " + maxX);
                     * System.out.println("MinY = " + minY);
                     * System.out.println("MaxY = " + maxY);
                     */

                    drawSegment(bkgGraphics, segment);

                    //if(placeNearCursor == null) {
                    if (Util.isInside(cursorCenterX, cursorCenterY, minX, minY, maxX, maxY)) {
                        for (int j = 0; j < segments[i].getNumberOfPoints() - 1; j++) {
                            int d = (int) Util.calculateDistancePoint2Line(cursorCenterX, cursorCenterY, segments[i].getX(j), segments[i].getY(j), segments[i].getX(j + 1), segments[i].getY(j + 1));

                            if (d < EPSILON) {
                                placeNearCursor = Util.decodeCharacters(paths[segments[i].getPathId()].getName());
                                break;
                            }
                        }
                    }
                    //}

                    /*
                    if(!is3D) {
                    if(paths[segment.getPathId()].getNamingSegmentId() == -1) {
                    if(sufficientLength(segment))
                    paths[segment.getPathId()].setNamingSegmentId(segment.getId());
                    }
                    }
                     */
                }
            }
            /*
            bkgGraphics.setColor(238, 221, 130);
            //System.out.println("CROSSROADSES: " + cross.length);
            for (int i = 0; i < cross.length; i++) {
            int x = cross[i].getX() & 0xFFFF;
            int y = cross[i].getY() & 0xFFFF;
            if (isInside(x, y)) {
            //System.out.println("Length = " + cross[i].getDistances()[0]);
            //System.out.println("Target = " + cross[i].getTargets()[0]);
            if (is3D) {
            drawCrossroads3D(bkgGraphics, cross[i]);
            } else {
            drawCrossroads(bkgGraphics, cross[i]);
            }
            }
            }
             */
            int point0, point1, x0, y0, x1, y1;

            /*
             * Draw saved GPS track
             */
            if (drawTrack) {
                //bkgGraphics.setColor(220, 220, 220); // gainsboro
                bkgGraphics.setColor(178, 34, 34); // firebrick
                for (int i = 0; i < track.size() - 1; i++) {
                    point0 = ((Integer) track.elementAt(i)).intValue();
                    point1 = ((Integer) track.elementAt(i + 1)).intValue();
                    x0 = (point0 >> 16) & 0xFFFF;
                    y0 = point0 & 0xFFFF;
                    x1 = (point1 >> 16) & 0xFFFF;
                    y1 = point1 & 0xFFFF;
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        //System.out.println("Before: " + x0 + " " + y0 + " " + x1 + " " + y1);
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        //System.out.println("After: " + x0 + " " + y0 + " " + x1 + " " + y1);
                        if (is3D) {
                            drawLine3D(bkgGraphics, x0, y0, x1, y1, 2);
                        } else {
                            drawLine(bkgGraphics, x0, y0, x1, y1, 2);
                        }
                    }
                }
            }

            /*
             * Draw result of location searching
             */
            bkgGraphics.setColor(0, 0, 0);

            /*
             * Draw shortest route
             */
            if (alg != null) {
                if (alg.getSegmentTrace().size() > 0) {
                    //bkgGraphics.setColor(230, 230, 250);
                    bkgGraphics.setColor(100, 149, 237);
                    drawRoute(bkgGraphics, 5);
                }
                if (alg.getSourceCrossroads() != null) {
                    //System.out.println("DRAW SRC");
                    routeSprite.setFrame(0);
                    routeSprite.setPosition(getXMap2Screen(alg.getSourceX()), getYMap2Screen(alg.getSourceY()));
                    if (is3D) {
                        Point point = new Point(routeSprite.getX(), routeSprite.getY());

                        if (assistDriving) {
                            point = MapRotation.rotate(point, currentPositionOnScreen, -rotationAngle);
                        }
                        warper.warpPoint(point);
                        routeSprite.setPosition(point.getX(), point.getY());
                    }
                    routeSprite.paint(bkgGraphics);
                }

                //int top = alg.getNumberOfPoints();
                if (alg.getDestinationCrossroads() != null) {
                    //System.out.println("DRAW DES");
                    routeSprite.setFrame(1);
                    routeSprite.setPosition(getXMap2Screen(alg.getDestinationX()), getYMap2Screen(alg.getDestinationY()));
                    if (is3D) {
                        Point point = new Point(routeSprite.getX(), routeSprite.getY());

                        if (assistDriving) {
                            point = MapRotation.rotate(point, currentPositionOnScreen, -rotationAngle);
                        }
                        warper.warpPoint(point);
                        routeSprite.setPosition(point.getX(), point.getY());
                    }
                    routeSprite.paint(bkgGraphics);

                    //top --;
                }

                Segment segment = null;
                int n = 0;
                for (int i = 0; i < alg.bannedSegmentsIds.size(); i++) {
                    segment = segments[((Integer) alg.bannedSegmentsIds.elementAt(i)).intValue()];
                    n = segment.getNumberOfPoints();
                    placeSprite.setFrame(24);
                    x0 = (segment.getX(n / 2 - 1) + segment.getX(n / 2)) / 2;
                    y0 = (segment.getY(n / 2 - 1) + segment.getY(n / 2)) / 2;
                    placeSprite.setPosition(getXMap2Screen(x0) - 8, getYMap2Screen(y0) - 8);
                    if (is3D) {
                        Point point = new Point(placeSprite.getX(), placeSprite.getY());

                        if (assistDriving) {
                            point = MapRotation.rotate(point, currentPositionOnScreen, -rotationAngle);
                        }
                        warper.warpPoint(point);
                        placeSprite.setPosition(point.getX(), point.getY());
                    }
                    placeSprite.paint(bkgGraphics);
                }
                /*
                System.out.println("TOP = " + top);
                routeSprite.setFrame(2);
                for(int i = 1; i < top; i ++) {
                routeSprite.setPosition(getXMap2Screen(alg.getPoint(i).getX()), getYMap2Screen(alg.getPoint(i).getY()));
                if(is3D) {
                Point point = new Point(routeSprite.getX(), routeSprite.getY());
                warper.warpPoint(point);
                routeSprite.setPosition(point.getX(), point.getY());
                }
                routeSprite.paint(bkgGraphics);
                System.out.println("INTERMEDIATE = " + i);
                }
                 */
                //pointer.paint(bkgGraphics);
            }

            if (drawArc) {

                bkgGraphics.setColor(32, 178, 170);
                for (int i = 0; i < location.length; i++) {
                    if(location[i] != null){
                        drawSegmentInRoute(bkgGraphics, location[i], 5);
                    }
                }
                
            }


            if (alg2 != null) {
                for (int i = 0; i < alg2.points.size(); i++) {
                    routeSprite.setFrame(2);
                    Point point = (Point) alg2.points.elementAt(i);
                    routeSprite.setPosition(getXMap2Screen(point.getX()), getYMap2Screen(point.getY()));
                    routeSprite.paint(bkgGraphics);
                }
                if (alg2.pairs != null) {
                    if (alg2.tsp != null) {
                        bkgGraphics.setColor(100, 149, 237);
                        for (int i = 0; i < alg2.tsp.route.length - 1; i++) {
                            drawRoute(bkgGraphics, alg2.pairs[alg2.tsp.route[i]][alg2.tsp.route[i + 1]], 5);
                        }
                    }
                }
            }
            /*
             * Draw street name
             */
            if (is3D || !midlet.getSettings().getStreetNameIsAlong()) {
                for (int i = paths.length - 1; i >= 0; i--) {
                    if (paths[i].getNamingSegmentId() != -1) {
                        Segment segment = segments[paths[i].getNamingSegmentId()];
                        int maxX = segment.getMaxX();
                        int maxY = segment.getMaxY();
                        int minX = segment.getMinX();
                        int minY = segment.getMinY();
                        if (Util.isIntersecting(minX, minY, maxX, maxY)) {
                            int x = segment.getX(segment.getNumberOfPoints() / 2 - 1);
                            int y = segment.getY(segment.getNumberOfPoints() / 2 - 1);
                            x += (segment.getX(segment.getNumberOfPoints() / 2) - x) / 2;
                            y += (segment.getY(segment.getNumberOfPoints() / 2) - y) / 2;
                            x = (x - MinX) * screenWidth / (MaxX - MinX);
                            y = (y - MinY) * screenHeight / (MaxY - MinY);
                            Point point = new Point(x, y);
                            if (!stopGPSThread && is3D) {
                                point = MapRotation.rotate(point, currentPositionOnScreen, -rotationAngle);
                            }
                            if (is3D) {
                                warper.warpPoint(point);
                                x = point.getX();
                                y = point.getY();
                            }
                            bkgGraphics.setColor(255, 0, 0);
                            bkgGraphics.fillArc(x - 2, y - 2, 4, 4, 0, 360);
                            bkgGraphics.setColor(0, 0, 0);
                            drawString(bkgGraphics, Util.decodeCharacters(paths[i].getName()), x, y);
                            paths[segment.getPathId()].setNamingSegmentId(-1);

                        }

                    }
                }
            } else {
                bkgGraphics.setColor(0, 0, 0);
                for (int i = paths.length - 1; i >= 0; i--) {
                    if (paths[i].getNamingSegmentId() != -1) {
                        Segment segment = segments[paths[i].getNamingSegmentId()];
                        int maxX = segment.getMaxX();
                        int maxY = segment.getMaxY();
                        int minX = segment.getMinX();
                        int minY = segment.getMinY();
                        if (Util.isIntersecting(minX, minY, maxX, maxY)) {
                            int width = getSegmentWidth(segment.getType(),
                                    zoomLevel);
                            if (width > 3) {
                                drawStreetName2(bkgGraphics, segment);
                                paths[segment.getPathId()].setNamingSegmentId(-1);
                            }
                        }
                    }
                }
            }

            /*
             * Draw POIs
             */
            if (zoomLevel > 2) {
                bkgGraphics.setColor(0, 0, 0);
                //System.out.println("LOCATIONS: " + locations.length);
                for (int i = 0; i < locations.length; i++) {
                    if (LayerConfig.isVisible(locations[i].getType())) {
                        drawPOI(bkgGraphics, locations[i]);
                    }

                    /*
                     * Show locations along this path
                     */
                    if (SearchPathForm.selectedPathId != -1) {
                        if (SearchPathForm.showLocationsAlongPath) {
                            /*
                            int segmentId = Util.findClosestSegment2(locations[i].getX(), locations[i].getY());
                            if(Util.contains(paths[SearchPathForm.selectedPathId].getSegments(), segmentId)) {
                            drawPOI(bkgGraphics, locations[i]);
                            }
                             */
                            for (int j = 0; j < paths[SearchPathForm.selectedPathId].getSegments().length; j++) {
                                if (Util.isInside(locations[i].getX(), locations[i].getY(),
                                        segments[paths[SearchPathForm.selectedPathId].getSegments()[j]].getMinX(),
                                        segments[paths[SearchPathForm.selectedPathId].getSegments()[j]].getMinY(),
                                        segments[paths[SearchPathForm.selectedPathId].getSegments()[j]].getMaxX(),
                                        segments[paths[SearchPathForm.selectedPathId].getSegments()[j]].getMaxY())) {
                                    drawPOI(bkgGraphics, locations[i]);
                                }
                            }
                        }
                    }
                }
                if (LayerConfig.showConstructionSite) {
                    drawConstructionSites(bkgGraphics);
                }
                for (int i = 0; i < userLocations.size(); i++) {
                    drawPOI(bkgGraphics, (SimpleLocation) userLocations.elementAt(i));
                }
            }

            /*
             * Only draw when running GPS thread
             */
            if (isInside(currentX, currentY) && !stopGPSThread) {
                drawCurrentPosition(bkgGraphics);
            }

            /*
             * Draw cursor
             */
            if (placeNearCursor != null) {
                if (!is3D) {
                    drawString(bkgGraphics, placeNearCursor, 5, 15);
                }
            } else {
                if (is3D) {
                    /*
                     * Draw sky, need or not???
                     */
                    //bkgGraphics.setColor(221, 238, 187);
                    //bkgGraphics.fillRect(0, 0, screenWidth, INSET_Y);

                    Point point = new Point(screenWidthDiv2, screenHeightDiv2);
                    int ret = warper.warpPoint(point);
                    if (ret != 0) {
                        double lat = Util.getLatitude((short) getYScreen2Map(point.getY()));
                        double lon = Util.getLongitude(getXScreen2Map(point.getX()));

                        //Beautify
                        lat = ((int) (lat * 100000)) * 1.0 / 100000;
                        lon = ((int) (lon * 100000)) * 1.0 / 100000;
                        bkgGraphics.setColor(255, 0, 0);
                        drawString(bkgGraphics, "LAT " + lat + ", LON " + lon, 5, 15);
                    }
                } else {
                    double lat = Util.getLatitude((short) cursorCenterY);
                    double lon = Util.getLongitude(cursorCenterX);

                    //Beautify
                    lat = ((int) (lat * 100000)) * 1.0 / 100000;
                    lon = ((int) (lon * 100000)) * 1.0 / 100000;

                    bkgGraphics.setColor(255, 0, 0);
                    drawString(bkgGraphics, "LAT " + lat + ", LON " + lon, 5, 15);
                }
            }

            //compassSprite.paint(bkgGraphics);
            cursor.paint(bkgGraphics);

            if (assistDriving && is3D) {
                if (RouteTrackingThread.warningSign != null) {
                    bkgGraphics.drawImage(RouteTrackingThread.warningSign, 0, 0, Graphics.TOP | Graphics.LEFT);
                }
            }
            /*
            System.out.println("TEST LAT_LON");
            double lat = 10.76614;
            double lon = 106.6755206;
            Point point = Util.createPoint(lon, lat);
            System.out.println("X = " + point.getX());
            System.out.println("Y = " + point.getY());
            if(isInside(point.getX(), point.getY())) {
            int x = (point.getX() - MinX) * screenWidth / (MaxX - MinX);
            int y = (point.getY() - MinY) * screenHeight / (MaxY - MinY);
            System.out.println("X_SCREEN = " + x);
            System.out.println("Y_SCREEN = " + y);
            }
             */

            g.drawImage(imageMap, 0, 0, Graphics.TOP | Graphics.LEFT);
            //System.out.println("ZOOM = " + zoomLevel);

            System.gc();
        }

        //System.out.println("TIME: " + (System.currentTimeMillis() - before));
    }


    /*
     * danh sach id path
     */
    public int[] listPathID(String strName) {
        //int[] lstPathId = new;
        int[] lst = new int[paths.length];
        int counter = 0;

        for (int i = 0; i < paths.length; i++) {
            String pathName = Util.decodeCharacters(paths[i].getName());
            pathName = VietnameseConverter.toTextNotMarked(pathName);
            if (pathName.equals(strName.toUpperCase())) {
                lst[counter] = i;
                counter++;
            }
        }
        if (counter != 0) {
            int[] lstPathID = new int[counter];
            for (int i = 0; i < counter; i++) {
                lstPathID[i] = lst[i];
            }
            return lstPathID;
        } else {
            return null;
        }
    }

    public int[] lstCrossRoadOfPath(int[] lstSegment) {
        int lengLst = lstSegment.length;
        int[] lstCrRoad = new int[lengLst + 1];

        lstCrRoad[0] = segments[lstSegment[0]].getCross0();
        lstCrRoad[1] = segments[lstSegment[0]].getCross1();

        int index = 2;

        for (int i = 1; i < lengLst; i++) {

            int point00 = segments[lstSegment[i]].getCross0();
            int point01 = segments[lstSegment[i]].getCross1();

            for (int j = 0; j < index; j++) {
                if (point00 == lstCrRoad[j]) {
                    lstCrRoad[index] = point01;
                    index++;
                    break;
                }
                if (point01 == lstCrRoad[j]) {
                    lstCrRoad[index] = point00;
                    index++;
                    break;
                }
            }

        }

        return lstCrRoad;
    }

    public int crRoadTarget(int[] lstCrRoad, String strCrRoad) {
        for (int i = 0; i < lstCrRoad.length; i++) {
            int[] lstSegmentOfCrRoad = cross[lstCrRoad[i]].getSegments();
            for (int j = 0; j < lstSegmentOfCrRoad.length; j++) {
                int pathid = segments[lstSegmentOfCrRoad[j]].getPathId();
                String pathName = Util.decodeCharacters(paths[pathid].getName());
                pathName = VietnameseConverter.toTextNotMarked(pathName);

                if (pathName.equals(strCrRoad)) {
                    return lstCrRoad[i];
                }
            }
        }
        return -1;
    }

    public Segment localizing(Graphics g, Path myPath, String strOfCrossRoad1, String strOfCrossRoad2) {
        //lay danh sach cac crossroad
        int[] lstSeg = myPath.getSegments();
        int[] lstCrossRoad = lstCrossRoadOfPath(lstSeg);

        // tương ứng mỗi crossroad là danh sách segment
        // lấy crossroad có tên con đường cắt

        int idCrossRoad0 = crRoadTarget(lstCrossRoad, strOfCrossRoad1);
        int idCrossRoad1 = crRoadTarget(lstCrossRoad, strOfCrossRoad2);


        if ((idCrossRoad1 != -1) && (idCrossRoad0 != -1)) {
            for (int i = 0; i < lstSeg.length; i++) {
                if (((segments[lstSeg[i]].getCross0() == idCrossRoad0) && (segments[lstSeg[i]].getCross1() == idCrossRoad1))
                        || ((segments[lstSeg[i]].getCross0() == idCrossRoad1) && (segments[lstSeg[i]].getCross1() == idCrossRoad0))) {
                    Util.centerScreen(segments[lstSeg[i]].getX(0), segments[lstSeg[i]].getY(0));
                    //drawSegmentInRoute(g, segments[lstSeg[i]], 5);
                    return segments[lstSeg[i]];
                }

            }
        }
        return null;
    }

    public Segment drawArcLocalized(Graphics g, String str, String strOfCrossRoad1, String strOfCrossRoad2) {
        //lay danh sach id cua path
        g.setColor(32, 178, 170);

        int[] lstPathID = listPathID(str);
        
        if (lstPathID != null) {
            for (int i = 0; i < lstPathID.length; i++) {
                Segment iLocation = localizing(g, paths[lstPathID[i]], strOfCrossRoad1, strOfCrossRoad2);
                if (iLocation != null) {
                    return iLocation;
                }
            }
        } else {
            // ko tim thay duong
        }
        return null;
    }

    /**
     * Called when a key is pressed.
     */
    protected void keyPressed(int keyCode) {
        int x = cursor.getX();
        int y = cursor.getY();
        switch (keyCode) {
            case KEY_STAR:
                if (alg == null) {
                    alg = new RoutingAlgorithm();
                }
                alg.setSource(cursorCenterX, cursorCenterY);

                if (alg.getDestinationCrossroads() != null) {
                    alg.setDestination(alg.getDestinationX(), alg.getDestinationY());
                    if (alg.getNumberOfPoints() > 2) {
                        alg.findHamiltonianPath();
                    } else {
                        if (alg.runDijstraAlg()) {
                            System.out.println("SUCCESSFUL FROM " + alg.getSourceCrossroads().getId() + " TO " + alg.getDestinationCrossroads().getId());
                            System.out.println(alg.routeToString());
                        }
                    }
                }
                repaint();
                break;
            case KEY_POUND:
                if (alg != null) {
                    alg.setSource(alg.getSourceX(), alg.getSourceY());
                    alg.setDestination(cursorCenterX, cursorCenterY);
                    long start = System.currentTimeMillis();
                    if (alg.getNumberOfPoints() > 2) {
                        alg.findHamiltonianPath();
                    } else {
                        if (alg.runDijstraAlg()) {
                            long end = System.currentTimeMillis();
                            System.out.println("SUCCESSFUL FROM " + alg.getSourceCrossroads().getId() + " TO " + alg.getDestinationCrossroads().getId() + " IN " + (end - start));
                            //System.out.println(alg.routeToString());
                            //route = alg.getSegmentTrace();
                            //repaint();
                            midlet.showBestRouteList();
                        } else {
                            //TODO: neu khong tim thay duong di thi sao???
                        }
                        /*
                         * Neu dang o che do driving assist thi de nguyen menu GPS
                         */
                        if (!assistDriving) {
                            contextMenu.detach(this);
                            contextMenu = new BestRouteContextMenu();
                            contextMenu.attach(this);
                        }
                    }
                    if (!stopGPSThread) {
                        //TODO: do something to save the world (TIM DUONG BANG DIJKSTRA VA CHAY DRIVING ASSIST)
                        System.out.println("SET");
                        moveToCurrentPosition = true;
                        new RouteTrackingThread(this).start();
                    }
                }
                break;
            case KEY_NUM2: // up
                if (MinY > MIN_Y) {
                    shift(0, -DY);
                    repaint();
                }
                break;
            case KEY_NUM4: // left
                if (MinX > MIN_X) {
                    shift(-DX, 0);
                    repaint();
                }
                break;
            case KEY_NUM6: // right
                if (MaxX < MAX_X) {
                    shift(DX, 0);
                    repaint();
                }
                break;
            case KEY_NUM8: // down
                if (MaxY < MAX_Y) {
                    shift(0, DY);
                    repaint();
                }
                break;
            case KEY_NUM3:
                if (zoomLevel < 5) {
                    zoomIn(100);
                    repaint();
                }
                break;
            case KEY_NUM1:
                if (zoomLevel > 1) {
                    zoomOut(100);
                    repaint();
                }
                break;
            case KEY_NUM5:
                is3D = !is3D;
                repaint();
                break;
            case KEY_NUM7:
                /*
                if(alg != null) {
                alg.addIntermediate(cursorCenterX, cursorCenterY);
                repaint();
                }
                 */
                if (alg2 == null) {
                    alg2 = new RoutingAlgorithm2();
                }
                alg2.add(cursorCenterX, cursorCenterY);
                repaint();
                /*
                rotationAngle --;
                if(rotationAngle == -1)
                rotationAngle = 35;
                compassSprite.setFrame(rotationAngle % 6);
                repaint();
                 */
                break;
            case KEY_NUM9:
                /*
                if(alg != null) {
                alg.removeIntermediate(cursorCenterX, cursorCenterY);
                repaint();
                }
                 */
                long s = System.currentTimeMillis();
                if (alg2 != null) {
                    alg2.add(cursorCenterX, cursorCenterY);
                    System.out.println("RESULT = " + alg2.run());
                    System.out.println("\nRESULT\n" + alg2.getResult() + "\nIN " + (System.currentTimeMillis() - s));
                    repaint();
                }
                /*
                rotationAngle ++;
                if(rotationAngle == 36)
                rotationAngle = 0;
                compassSprite.setFrame(rotationAngle % 6);
                if((rotationAngle / 6) == 1)
                compassSprite.setTransform(Sprite.TRANS_ROT90);
                else if((rotationAngle / 6) == 2)
                compassSprite.setTransform(Sprite.TRANS_ROT180);
                else if((rotationAngle / 6) == 3)
                compassSprite.setTransform(Sprite.TRANS_ROT270);
                else if((rotationAngle / 6) == 4)
                compassSprite.setTransform(Sprite.TRANS_NONE);
                repaint();
                 */
                break;

            case KEY_NUM0:
                /*if (midlet.locationForm != null) {
                midlet.locationForm.centerNextPlace();
                repaint();
                }*/
                if (drawArc == false) {
                    drawArc = true;
                }

                if (drawArc == true) {
                    //location = new Segment[1];
                    //location[0] = drawArcLocalized(bkgGraphics, "BA HAT", "NGUYEN TRI PHUONG", "NGUYEN TIEU LA");
                    //location = drawArcLocalized(bkgGraphics, "LE QUY DON", "VO VAN TAN", "NGUYEN THI MINH KHAI");
                    //location = drawArcLocalized(bkgGraphics, "LE QUY DON", "VO VAN TAN", "DUONG TRONG DINH THONG NHAT");
                    //drawArcLocalized(bkgGraphics, "NGUYEN THI MINH KHAI", "NGUYEN THIEN THUAT", "CAO THANG");
                    //drawArcLocalized(bkgGraphics, "LY THAI TO", "HO THI KY", "LE HONG PHONG");
                    //drawArcLocalized(bkgGraphics, "NGUYEN THI MINH KHAI", "NGUYEN VAN CU", "NGUYEN THIEN THUAT");
                    //drawArcLocalized(bkgGraphics, "NGUYEN THI MINH KHAI", "LY THAI TO", "NGUYEN THIEN THUAT");
                    //drawArcLocalized(bkgGraphics, "NGUYEN VAN CU", "AN DUONG VUONG", "HUNG VUONG");
                    //drawArcLocalized(bkgGraphics, "NGUYEN VAN CU", "AN DUONG VUONG", "NGUYEN TRAI");
                    //System.out.println("draw arc !");
                    try {
                        //ArrayOfString arr = service.search(imei, Integer.parseInt(cellid), time);
                       //ArrayOfString arr = Connector.service.search("12", 237289571, time);
                        //ArrayOfString arr = service.search("12", 237289571, time);
                        //String[] result = arr.getString();
                        if (Connector.service == null) {
                            Alert alert = new Alert("Warnning !");
                            alert.setString("Connect CellService First!!!");
                            Display.getDisplay(midlet).setCurrent(alert);
                            break;
                        }
                        String[] result = Connector.t.getResult();

                        location = new Segment[result.length];

                        for (int i = 0; i < result.length; i++) {
                            String str01 = VietnameseConverter.toTextNotMarked(result[i++]);
                            String str02 = VietnameseConverter.toTextNotMarked(result[i++]);
                            String str03 = VietnameseConverter.toTextNotMarked(result[i]);

                            location[i] = drawArcLocalized(bkgGraphics, str01, str02, str03);
                        }
                    } catch (Exception e) {
                    }

                    drawArc = true;
                    repaint();
                }


                break;
            case NokiaKeyDef.NOKIA_KEY_RIGHT_ARROW:
                cursor.setPosition(cursor.getX() + CURSOR_STEP, cursor.getY());
                if ((x + 20) >= screenWidth) {
                    cursor.setPosition(screenWidth - 20, y);
                    keyPressed(Canvas.KEY_NUM6);
                } else {
                    repaint();
                }
                break;
            case NokiaKeyDef.NOKIA_KEY_LEFT_ARROW:
                cursor.setPosition(cursor.getX() - CURSOR_STEP, cursor.getY());
                if (x <= 0) {
                    cursor.setPosition(0, y);
                    keyPressed(Canvas.KEY_NUM4);
                } else {
                    repaint();
                }
                break;
            case NokiaKeyDef.NOKIA_KEY_UP_ARROW:
                cursor.setPosition(cursor.getX(), cursor.getY() - CURSOR_STEP);
                if (y <= 0) {
                    cursor.setPosition(x, 0);
                    keyPressed(Canvas.KEY_NUM2);
                } else {
                    repaint();
                }
                break;
            case NokiaKeyDef.NOKIA_KEY_DOWN_ARROW:
                cursor.setPosition(cursor.getX(), cursor.getY() + CURSOR_STEP);
                if (y >= screenHeight) {
                    cursor.setPosition(x, screenHeight);
                    keyPressed(Canvas.KEY_NUM8);
                } else {
                    repaint();
                }
                break;
            default:
                break;
        }
    }

    /**
     * Called when a key is released.
     */
    protected void keyReleased(int keyCode) {
    }

    /**
     * Called when a key is repeated (held down).
     */
    protected void keyRepeated(int keyCode) {
        keyPressed(keyCode);
    }

    /**
     * Called when the pointer is dragged.
    w */
    protected void pointerDragged(int x, int y) {
    }

    /**
     * Called when the pointer is pressed.
     */
    protected void pointerPressed(int x, int y) {
    }

    /**
     * Called when the pointer is released.
     */
    protected void pointerReleased(int x, int y) {
    }

    /**
     * Called when action should be handled
     */
    public void commandAction(Command command, Displayable displayable) {
        //TODO: implement CommandListener (deprecated)
    }

    public void commandAction(int actionCode) {
        switch (actionCode) {
            case ActionCode.GO_TO_SOURCE:
                if (alg != null) {
                    if (alg.getSourceCrossroads() != null) {
                        Util.centerScreen(alg.getSourceX(), alg.getSourceY());
                        repaint();
                    }
                }
                break;
            case ActionCode.GO_TO_DESTINATION:
                if (alg != null) {
                    if (alg.getDestinationCrossroads() != null) {
                        Util.centerScreen(alg.getDestinationX(), alg.getDestinationY());
                        repaint();
                    }
                }
                break;
            case ActionCode.SAVE_CURRENT_POSITION:
                //midlet.showSaveCurPosForm();
                //System.out.println("asdfadsfasdfa");
                break;
            case ActionCode.SHOW_TRACKLOG_FORM:
                midlet.showRouteList();
                break;
            case ActionCode.REFRESH_BEST_ROUTE:
                if (alg != null) {
                    if (alg.getSourceCrossroads() != null && alg.getDestinationCrossroads() != null) {
                        alg.setSource(alg.getSourceX(), alg.getSourceY());
                        alg.setDestination(alg.getDestinationX(), alg.getDestinationY());
                        alg.runDijstraAlg();
                    }
                }
                break;
            case ActionCode.SHOW_LOCATIONS_ALONG_PATH:
                SearchPathForm.showLocationsAlongPath = true;
                repaint();
                break;
            case ActionCode.SHOW_MENU:
                midlet.showMenuCanvas();
                break;
            case ActionCode.SHOW_MAP:
                contextMenu.detach(this);
                contextMenu = new GlobalContextMenu();
                contextMenu.attach(this);
                midlet.showMapCanvas();
                break;
            case ActionCode.RUN_GPS:
                if (stopGPSThread) {
                    is3D = false;
                    zoomLevel = 5;
                    searchGPS(5000);
                } else {
                    stopGPSThread = true;
                }
                contextMenu.detach(this);
                contextMenu = new GPSContextMenu();
                contextMenu.attach(this);
                break;

            case ActionCode.SEARCH_PATH:
                midlet.showSearchPathForm();
                contextMenu.detach(this);
                contextMenu = new SearchPathContextMenu();
                contextMenu.attach(this);
                break;
            case ActionCode.SEARCH_LOCATION:
                midlet.showLocationForm();
                contextMenu.detach(this);
                contextMenu = new SearchLocationContextMenu();
                contextMenu.attach(this);
                break;
            case ActionCode.SHOW_BEST_ROUTE:
                if (alg != null) {
                    if (alg.getSourceCrossroads() != null && alg.getDestinationCrossroads() != null) {
                        midlet.showBestRouteList();
                    }
                }
                break;
            case ActionCode.TAKE_PICTURE:
                midlet.showVideoCanvas();
                break;
            case ActionCode.ASSIST_DRIVING:
                assistDriving = !assistDriving;
                //System.out.println("TRACKING");
                if (assistDriving) {
                    if (alg != null) {
                        alg.setSourceCrossroads(null);
                        alg.setDestinationCrossroads(null);
                        alg.setDirectionTowardDestination(0);
                        alg.setDirectionTowardSource(0);
                    } else {
                        alg = new RoutingAlgorithm();
                    }

                    is3D = true;

                    if (stopGPSThread) {
                        is3D = false;
                        zoomLevel = 5;
                        searchGPS(5000);
                    } else {
                        stopGPSThread = true;
                    }
                    contextMenu.detach(this);
                    contextMenu = new GPSContextMenu();
                    contextMenu.attach(this);
                }
                break;
            case ActionCode.SHOW_SETTINGS_FORM:
                midlet.showSettingsForm();
                break;
            case ActionCode.DESTROY_APP:
                midlet.destroyApp(true);
                break;
            case ActionCode.CLEAR_BEST_ROUTE:
                //clear best route
                if (alg != null) {
                    /*
                    alg.setSourceCrossroads(null);
                    alg.setDestinationCrossroads(null);
                    alg.setDirectionTowardDestination(0);
                    alg.setDirectionTowardSource(0);
                     */
                    alg = null;
                }
                break;
            case ActionCode.SHOW_REGISTER_FORM:
                //TODO: ActionCode for testing
                midlet.showRegisterForm();
                break;
            case ActionCode.SHOW_GPS_SATELLITES:
                midlet.showSatelliteCanvas();
                break;
            case ActionCode.SHOW_GPS_SKY:
                midlet.showSkyCanvas();
                break;
            case ActionCode.BAN_UNBAN_SEGMENT:
                if (alg != null) {
                    if (alg.getDestinationCrossroads() != null) {
                        int segmentId = Util.findClosestSegment2(cursorCenterX, cursorCenterY);

                        if (segmentId != -1) {

                            System.out.println("NEW SEGMENT ID = " + segmentId);

                            if (alg.bannedSegmentsIds.contains(new Integer(segmentId))) {
                                alg.bannedSegmentsIds.removeElement(new Integer(segmentId));
                            } else {
                                alg.bannedSegmentsIds.addElement(new Integer(segmentId));
                            }

                            System.out.print("BANNED SEGMENT IDS: ");
                            for (int i = 0; i < alg.bannedSegmentsIds.size(); i++) {
                                System.out.print(alg.bannedSegmentsIds.elementAt(i) + " ");
                            }
                            System.out.println();

                            //Buoc phai gan lai src va dest thi
                            //segmentTrace va crossroadsTrace moi cap nhat
//--> CAN SUA LAI --> CHAY DUOC ROI
                            alg.setSource(alg.getSourceX(), alg.getSourceY());
                            alg.setDestination(alg.getDestinationX(), alg.getDestinationY());
                            alg.runDijstraAlg();
                            repaint();
                        }
                    }
                }
                break;
            case ActionCode.SHOW_LAYER_LIST:
                MapDrawer.getMidlet().show(new LayerList());
                break;
            case ActionCode.RECORD_AUDIO:
                midlet.showRecorderForm();
                break;
            default:
                break;
        }
    }

    public void drawLine3D(Graphics g, int x0, int y0, int x1, int y1, int width) {
        int dx = 0;
        int dy = 0;

        int tempWidth = width;
        if (Math.abs(x1 - x0) >= Math.abs(y1 - y0)) {
            // horizontal line


            do {
                dy += 1;
            } while (--width != 0);

            fillArc3D(g, x1 - tempWidth + 1, y1 - tempWidth + 1, tempWidth + tempWidth - 2, tempWidth + tempWidth - 2, 0, 360);
            fillPolygon(g, x0, y0, x1, y1, dx, dy);
            //g.drawLine(x0 + 1, y0-dy, x1, y1-dy);
            //g.drawLine(x0 + 1, y0+dy, x1, y1+dy);
        } else {
            // vertical line


            do {
                dx += 1;
            } while (--width != 0);
            fillArc3D(g, x1 - tempWidth + 1, y1 - tempWidth + 1, tempWidth + tempWidth - 2, tempWidth + tempWidth - 2, 0, 360);

            fillPolygon(g, x0, y0, x1, y1, dx, dy);
            //g.drawLine(x0-dx, y0, x1-dx, y1);
            //g.drawLine(x0+dx, y0, x1+dx, y1);
        }
    }

    public void fillArc3D(Graphics g, int xLeft, int yLeft, int width, int height, int startAngle, int arcAngle) {
        int xRight = xLeft + width;
        int yRight = yLeft + height;
        Point pointLeft = new Point(xLeft, yLeft);
        Point pointRight = new Point(xRight, yRight);
        int ret = warper.warpPoint(pointLeft)
                + warper.warpPoint(pointRight);
        if (ret == 2) {
            xLeft = pointLeft.getX();
            yLeft = pointLeft.getY();
            xRight = pointRight.getX();
            yRight = pointRight.getY();
            g.fillArc(xLeft, yLeft, xRight - xLeft, yRight - yLeft, startAngle, arcAngle);
        }
    }

    public static void drawLine(Graphics g, int x0, int y0, int x1, int y1, int width) {
        g.drawLine(x0, y0, x1, y1);

        int dx = 0;
        int dy = 0;

        int tempWidth = width;
        if (Math.abs(x1 - x0) >= Math.abs(y1 - y0)) {
            // horizontal line

            do {
                dy += 1;
                g.drawLine(x0, y0 - dy, x1, y1 - dy);
                g.drawLine(x0, y0 + dy, x1, y1 + dy);
            } while (--width != 0);

            g.fillRoundRect(x1 - tempWidth + 1, y1 - tempWidth + 1, tempWidth + tempWidth - 2, tempWidth + tempWidth - 2, tempWidth + tempWidth - 2, tempWidth + tempWidth - 2);
        } else {
            // vertical line


            do {
                dx += 1;
                g.drawLine(x0 - dx, y0, x1 - dx, y1);
                g.drawLine(x0 + dx, y0, x1 + dx, y1);
            } while (--width != 0);

            g.fillRoundRect(x1 - tempWidth + 1, y1 - tempWidth + 1, tempWidth + tempWidth - 2, tempWidth + tempWidth - 2, tempWidth + tempWidth - 2, tempWidth + tempWidth - 2);
        }
    }

    private void fillPolygon(Graphics g, int x0, int y0, int x1, int y1, int dx, int dy) {
        int[] _x = new int[4];
        int[] _y = new int[4];
        if (Math.abs(x1 - x0) >= Math.abs(y1 - y0)) {
            _x[3] = x0 + 1;
            _x[2] = x1;
            _x[0] = x0 + 1;
            _x[1] = x1;

            _y[3] = y0 - dy;
            _y[2] = y1 - dy;
            _y[0] = y0 + dy;
            _y[1] = y1 + dy;
        } else {
            _x[3] = x0 - dx;
            _x[2] = x1 - dx;
            _x[0] = x0 + dx;
            _x[1] = x1 + dx;

            _y[3] = y0;
            _y[2] = y1;
            _y[0] = y0;
            _y[1] = y1;
        }
        /*
        _x[0] = warper.warpX(_x[0], _y[0]);
        _y[0] = warper.warpY(_x[0], _y[0]);
        _x[1] = warper.warpX(_x[1], _y[1]);
        _y[1] = warper.warpY(_x[1], _y[1]);
        _x[2] = warper.warpX(_x[2], _y[2]);
        _y[2] = warper.warpY(_x[2], _y[2]);
        _x[3] = warper.warpX(_x[3], _y[3]);
        _y[3] = warper.warpY(_x[3], _y[3]);
         */
        if (warper.warpPoints(_x, _y) == 4) {
            PolygonUtil.fillPolygon(g, _x, _y);
        }
    }

    public void drawSegment(Graphics g, Segment segment) {
        byte type = segment.getType();
        if (zoomLevel == 0 && (type > 1 && type < 8)) {
            return;
        }
        if (zoomLevel == 1 && (type > 2 && type < 8)) {
            return;
        }
        if ((zoomLevel == 2 || zoomLevel == 3) && (type > 3 && type < 8)) {
            return;
        }

        Path path = paths[segment.getPathId()];
        byte[] name = path.getName();

        int x0 = 0;
        int y0 = 0;
        int x1 = 0;
        int y1 = 0;

        int width = getSegmentWidth(type, zoomLevel);

        int start = 0; //for name placement

        //System.out.println("TYPE = " + type + " " + width);
		/*
        if(width == 6)
        g.setColor(95, 158, 160);
        else if(width == 8)
        g.setColor(238, 221, 130);
        else
        g.setColor(255, 255, 255);
         */

        g.setColor(255, 255, 255);
        if (type < 3) {
            g.setColor(255, 255, 119);
        }
        if (segment.getPathId() == SearchPathForm.selectedPathId) {
            g.setColor(95, 158, 160);
        }

        int n = segment.getNumberOfPoints();
        for (int i = 0; i < n - 1; i++) {
            x0 = segment.getX(i) & 0xFFFF;
            y0 = segment.getY(i) & 0xFFFF;
            x1 = segment.getX(i + 1) & 0xFFFF;
            y1 = segment.getY(i + 1) & 0xFFFF;

            if (shouldRenderLine(x0, y0, x1, y1)) {
                x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
                y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
                x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
                y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

                /*
                 * Check length for name placement
                 */
                if (!is3D) {
                    if (width > 3) {
                        if (path.getNamingSegmentId() == -1) {
                            if (x1 < x0) {
                                start = stringDrawer.check(name, x1, y1, x0, y0, start);
                            } else {
                                start = stringDrawer.check(name, x0, y0, x1, y1, start);
                            }
                            if (start == name.length) {
                                paths[segment.getPathId()].setNamingSegmentId(segment.getId());
                            }
                        }
                    }
                } else {
                    if (path.getNamingSegmentId() == -1) {
                        paths[segment.getPathId()].setNamingSegmentId(segment.getId());
                    }

                    if (!stopGPSThread) {
                        /*
                         * Rotation
                         */
                        Point point0 = new Point(x0, y0);
                        Point point1 = new Point(x1, y1);
                        point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                        point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                        x0 = point0.getX();
                        y0 = point0.getY();
                        x1 = point1.getX();
                        y1 = point1.getY();
                    }

                }


                /*
                 * Clipping
                 */
                if (x0 < 0) {
                    if (x1 < 0) {
                        continue;
                    }
                    y0 += (y1 - y0) * (-x0) / (x1 - x0);
                    x0 = 0;
                } else if (x0 > screenWidth) {
                    if (x1 > screenWidth) {
                        continue;
                    }
                    y0 += (y1 - y0) * (screenWidth - x0) / (x1 - x0);
                    x0 = screenWidth;
                }
                if (x1 < 0) {
                    y1 += (y0 - y1) * (-x1) / (x0 - x1);
                    x1 = 0;
                } else if (x1 > screenWidth) {
                    y1 += (y0 - y1) * (screenWidth - x1) / (x0 - x1);
                    x1 = screenWidth;
                }
                if (y0 < 0) {
                    if (y1 < 0) {
                        continue;
                    }
                    x0 += (x1 - x0) * (-y0) / (y1 - y0);
                    y0 = 0;
                } else if (y0 > screenHeight) {
                    if (y1 > screenHeight) {
                        continue;
                    }
                    x0 += (x1 - x0) * (screenHeight - y0) / (y1 - y0);
                    y0 = screenHeight;
                }
                if (y1 < 0) {
                    x1 += (x0 - x1) * (-y1) / (y0 - y1);
                    y1 = 0;
                } else if (y1 > screenHeight) {
                    x1 += (x0 - x1) * (screenHeight - y1) / (y0 - y1);
                    y1 = screenHeight;
                }
                /*
                if(path.getMinX() > x0) {
                path.setMinX(x0);
                path.setFirstPoint((byte)i);
                }
                if(path.getMinX() > x1) {
                path.setMinX(x1);
                path.setFirstPoint((byte)(i + 1));
                }
                if(path.getMaxX() < x0)
                path.setMaxX(x0);
                if(path.getMaxX() < x1)
                path.setMaxX(x1);

                if(path.getMinY() > y0)
                path.setMinY(y0);
                if(path.getMinY() > y1)
                path.setMinX(y1);
                if(path.getMaxY() < y0)
                path.setMaxY(y0);
                if(path.getMaxY() < y1)
                path.setMaxY(y1);
                 */
                /*
                Point point = quadMap.map(x0, y0);
                x0 = point.getX();
                y0 = point.getY();
                point = quadMap.map(x1, y1);
                x1 = point.getX();
                y1 = point.getY();
                 */
                /*
                int distance = (int)Math.sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
                path.setLength(path.getLength() + distance - StringDrawer.DELTA);
                 */
                if (is3D) {
                    drawLine3D(g, x0, y0, x1, y1, width);
                } else {
                    drawLine(g, x0, y0, x1, y1, width);
                    //System.out.println("Type2 = " + segment.getType2());
		/*
                     * Con sai o BA HUYEN THANH QUAN hoac TRUONG DINH
                     */
                    if (segment.getType2() != 0) {
                        /*
                         * Xet type2 de biet co ve mui ten chi chieu hay khong
                         * Mui ten ve o doan thang giua segment
                         */

                        x0 = segment.getX(n / 2 - 1);
                        y0 = segment.getY(n / 2 - 1);
                        x1 = segment.getX(n / 2);
                        y1 = segment.getY(n / 2);

                        if (shouldRenderLine(x0, y0, x1, y1)) {
                            /*
                            if(segment.getPathId() == 1017 || segment.getPathId() == 1018) {
                            System.out.println("------------------------");
                            System.out.println("Path " + segment.getPathId());
                            System.out.println("Segment " + segment.getId());
                            System.out.println("X0 = " + x0 + " = " + Util.getLongitude(x0));
                            System.out.println("Y0 = " + y0 + " = " + Util.getLatitude((short)y0));
                            System.out.println("X1 = " + x1 + " = " + Util.getLongitude(x1));
                            System.out.println("Y1 = " + y1 + " = " + Util.getLatitude((short)y1));
                            }
                             */
                            if (y1 > y0) {
                                x0 = getXMap2Screen(x0);
                                y0 = getYMap2Screen(y0);
                                x1 = getXMap2Screen(x1);
                                y1 = getYMap2Screen(y1);
                                arrowDrawer.draw(g, x0, y0, x1, y1, true);
                            } else {
                                x0 = getXMap2Screen(x0);
                                y0 = getYMap2Screen(y0);
                                x1 = getXMap2Screen(x1);
                                y1 = getYMap2Screen(y1);

                                arrowDrawer.draw(g, x0, y0, x1, y1, false);
                            }

                            /*
                            if(segment.getType2() == 1)
                            arrowDrawer.draw(g, x0, y0, x1, y1, true);
                            else
                            arrowDrawer.draw(g, x0, y0, x1, y1, false);
                             */
                            //arrowDrawer.draw(g, x0, y0, x1, y1, true);
                        }
                    }
                }
            }
        }

    }

    public void drawRoute(Graphics g, int width) {
        /*
         * HINH NHU XET 1 CHIEU ROI
         */
        if (alg.getSourceCrossroads() == null || alg.getDestinationCrossroads() == null) {
            return;
        }

        // Draw from source to projection
        // vẽ từ điểm nguồn được chọn tới segment con dg gần nhất
        int x0 = alg.getSourceX();
        int y0 = alg.getSourceY();
        int x1 = alg.getProjectionSourceX();
        int y1 = alg.getProjectionSourceY();

        if (shouldRenderLine(x0, y0, x1, y1)) {
            x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
            y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
            x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
            y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

            if (is3D) {
                if (assistDriving) { //truoc day la !stopGPSThread
                    /*
                     * Rotation
                     */
                    Point point0 = new Point(x0, y0);
                    Point point1 = new Point(x1, y1);
                    point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                    point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                    x0 = point0.getX();
                    y0 = point0.getY();
                    x1 = point1.getX();
                    y1 = point1.getY();
                }
                drawLine3D(g, x0, y0, x1, y1, width);
            } else {
                drawLine(g, x0, y0, x1, y1, width);
            }

            //g.fillArc(x1 - 5, y1 - 5, 10, 10, 0, 360);
        }

        // Draw from destination to projection
        // vẽ từ điểm đích dc chọn tới con dg gần nhất
        x0 = alg.getDestinationX();
        y0 = alg.getDestinationY();
        x1 = alg.getProjectionDestinationX();
        y1 = alg.getProjectionDestinationY();

        if (shouldRenderLine(x0, y0, x1, y1)) {
            x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
            y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
            x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
            y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

            if (is3D) {
                if (assistDriving) { //truoc day la !stopGPSThread
                    /*
                     * Rotation
                     */
                    Point point0 = new Point(x0, y0);
                    Point point1 = new Point(x1, y1);
                    point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                    point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                    x0 = point0.getX();
                    y0 = point0.getY();
                    x1 = point1.getX();
                    y1 = point1.getY();
                }

                drawLine3D(g, x0, y0, x1, y1, width);
            } else {
                drawLine(g, x0, y0, x1, y1, width);
            }

            //g.fillArc(x1 - 5, y1 - 5, 10, 10, 0, 360);
        }

        /*
         * Xet rieng truong hop diem dau va diem cuoi nam cung segment
         */
        if (alg.getSourceClosestSegmentId() == alg.getDestinationClosestSegmentId()) {
            Segment segment = segments[alg.getSourceClosestSegmentId()];
            int bottom = alg.getSourceClosestPointIndex();
            int top = alg.getDestinationClosestPointIndex();

            System.out.println("BOTTOM = " + bottom);
            System.out.println("TOP = " + top);

            if (bottom == top) {
                /*
                 * Khi chung diem gan nhat tren segment thi diem gan nhat nay khong the nam giua 2 diem chieu
                 */
                x0 = alg.getProjectionSourceX();
                y0 = alg.getProjectionSourceY();
                x1 = alg.getProjectionDestinationX();
                y1 = alg.getProjectionDestinationY();
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = getXMap2Screen(x0);
                    y0 = getYMap2Screen(y0);
                    x1 = getXMap2Screen(x1);
                    y1 = getYMap2Screen(y1);
                    if (is3D) {
                        if (assistDriving) { //truoc day la !stopGPSThread
                            /*
                             * Rotation
                             */
                            Point point0 = new Point(x0, y0);
                            Point point1 = new Point(x1, y1);
                            point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                            point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                            x0 = point0.getX();
                            y0 = point0.getY();
                            x1 = point1.getX();
                            y1 = point1.getY();
                        }
                        drawLine3D(g, x0, y0, x1, y1, width);
                    } else {
                        drawLine(g, x0, y0, x1, y1, width);
                    }
                }
            } else {

                if (bottom > top) {
                    int temp = top;
                    top = bottom;
                    bottom = temp;
                }

                bottom++;

                for (int i = bottom; i < top; i++) {
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                    x1 = segment.getX(i + 1);
                    y1 = segment.getY(i + 1);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                }

                x0 = alg.getProjectionSourceX();
                y0 = alg.getProjectionSourceY();
                x1 = segment.getX(bottom);
                y1 = segment.getY(bottom);
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = getXMap2Screen(x0);
                    y0 = getYMap2Screen(y0);
                    x1 = getXMap2Screen(x1);
                    y1 = getYMap2Screen(y1);
                    if (is3D) {

                        if (assistDriving) { //truoc day la !stopGPSThread
                            /*
                             * Rotation
                             */
                            Point point0 = new Point(x0, y0);
                            Point point1 = new Point(x1, y1);
                            point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                            point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                            x0 = point0.getX();
                            y0 = point0.getY();
                            x1 = point1.getX();
                            y1 = point1.getY();
                        }
                        drawLine3D(g, x0, y0, x1, y1, width);
                    } else {
                        drawLine(g, x0, y0, x1, y1, width);
                    }
                }

                x0 = alg.getProjectionDestinationX();
                y0 = alg.getProjectionDestinationY();
                x1 = segment.getX(top);
                y1 = segment.getY(top);
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = getXMap2Screen(x0);
                    y0 = getYMap2Screen(y0);
                    x1 = getXMap2Screen(x1);
                    y1 = getYMap2Screen(y1);
                    if (is3D) {

                        if (assistDriving) { //truoc day la !stopGPSThread
                            /*
                             * Rotation
                             */
                            Point point0 = new Point(x0, y0);
                            Point point1 = new Point(x1, y1);
                            point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                            point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                            x0 = point0.getX();
                            y0 = point0.getY();
                            x1 = point1.getX();
                            y1 = point1.getY();
                        }
                        drawLine3D(g, x0, y0, x1, y1, width);
                    } else {
                        drawLine(g, x0, y0, x1, y1, width);
                    }
                }
            }
        } else {
            /*
             * Ve cac segment o giua
             */
            for (int i = 1; i < alg.getSegmentTrace().size() - 1; i++) {
                Segment segment = (Segment) alg.getSegmentTrace().elementAt(i);
                int maxX = segment.getMaxX();
                int maxY = segment.getMaxY();
                int minX = segment.getMinX();
                int minY = segment.getMinY();
                if (Util.isIntersecting(minX, minY, maxX, maxY)) {
                    drawSegmentInRoute(g, segment, width);
                }
            }

            // Draw from projection to source crossroads
            x1 = alg.getSourceCrossroads().getX();
            y1 = alg.getSourceCrossroads().getY();
            //g.fillArc(getXMap2Screen(x1) - 5, getYMap2Screen(y1) - 5, 10, 10, 0, 360);
            x0 = alg.getProjectionSourceX();
            y0 = alg.getProjectionSourceY();

            Segment segment = segments[alg.getSourceClosestSegmentId()];
            //g.fillArc(segment.getX(alg.getSourceClosestPointIndex()) - 5, segment.getY(alg.getSourceClosestPointIndex()) - 5, 10, 10, 0, 360);

            if (alg.getDirectionTowardSource() == 1) {
                int i = alg.getSourceClosestPointIndex();
                for (; i < segment.getNumberOfPoints(); i++) {
                    x1 = segment.getX(i);
                    y1 = segment.getY(i);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                }
            } else if (alg.getDirectionTowardSource() == -1) {
                int i = alg.getSourceClosestPointIndex();
                for (; i > -1; i--) {
                    x1 = segment.getX(i);
                    y1 = segment.getY(i);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                }
            }

            // Draw from projection to destination crossroads
            x1 = alg.getDestinationCrossroads().getX();
            y1 = alg.getDestinationCrossroads().getY();
            //g.fillArc(getXMap2Screen(x1) - 5, getYMap2Screen(y1) - 5, 10, 10, 0, 360);
            x0 = alg.getProjectionDestinationX();
            y0 = alg.getProjectionDestinationY();

            segment = MapCanvas.segments[alg.getDestinationClosestSegmentId()];
            //g.fillArc(segment.getX(alg.getDestinationClosestPointIndex()) - 5, segment.getY(alg.getDestinationClosestPointIndex()) - 5, 10, 10, 0, 360);

            if (alg.getDirectionTowardDestination() == 1) {
                int i = alg.getDestinationClosestPointIndex();
                for (; i < segment.getNumberOfPoints(); i++) {
                    x1 = segment.getX(i);
                    y1 = segment.getY(i);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                }
            } else if (alg.getDirectionTowardDestination() == -1) {
                int i = alg.getDestinationClosestPointIndex();
                for (; i > -1; i--) {
                    x1 = segment.getX(i);
                    y1 = segment.getY(i);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                }
            }
        }
        if (alg.getSourceClosestSegmentId() != alg.getDestinationClosestSegmentId()) {
            /*
             * Ve cac mui ten chi huong di
             */
            for (int i = alg.getCrossroadsTrace().size() - 2; i > 1; i--) {
                Segment segment = segments[RoutingAlgorithm.getAdjacentSegmentId2(
                        ((Crossroads) alg.getCrossroadsTrace().elementAt(i)).getId(),
                        ((Crossroads) alg.getCrossroadsTrace().elementAt(i - 1)).getId())];
                Crossroads crossroads = (Crossroads) alg.getCrossroadsTrace().elementAt(i);
                if (crossroads.getX() == segment.getX(0) && crossroads.getY() == segment.getY(0)) {
                    x0 = segment.getX(0) & 0xFFFF;
                    y0 = segment.getY(0) & 0xFFFF;
                    x1 = segment.getX(1) & 0xFFFF;
                    y1 = segment.getY(1) & 0xFFFF;
                } else {
                    x0 = segment.getX(segment.getNumberOfPoints() - 1) & 0xFFFF;
                    y0 = segment.getY(segment.getNumberOfPoints() - 1) & 0xFFFF;
                    x1 = segment.getX(segment.getNumberOfPoints() - 2) & 0xFFFF;
                    y1 = segment.getY(segment.getNumberOfPoints() - 2) & 0xFFFF;
                }

                if (isInside(x0, y0) && isInside(x1, y1)) {
                    x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
                    y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
                    x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
                    y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

                    if (assistDriving) { //truoc day la !stopGPSThread
                        /*
                         * Rotation
                         */
                        Point point0 = new Point(x0, y0);
                        Point point1 = new Point(x1, y1);
                        point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                        point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                        x0 = point0.getX();
                        y0 = point0.getY();
                        x1 = point1.getX();
                        y1 = point1.getY();
                    }
                    if (is3D) {
                        Point point0 = new Point(x0, y0);
                        Point point1 = new Point(x1, y1);
                        warper.warpPoint(point0);
                        warper.warpPoint(point1);
                        x0 = point0.getX();
                        y0 = point0.getY();
                        x1 = point1.getX();
                        y1 = point1.getY();
                    }
                    int color = g.getColor();
                    g.setColor(244, 164, 96);
                    DirectionArrowDrawer.draw(g, x0, y0, x1, y1, 5);
                    g.setColor(color);
                }
            }
        }
    }

    public void drawRoute(Graphics g, RoutingAlgorithm alg, int width) {
        /*
         * HINH NHU XET 1 CHIEU ROI
         */
        if (alg.getSourceCrossroads() == null || alg.getDestinationCrossroads() == null) {
            return;
        }

        // Draw from source to projection
        int x0 = alg.getSourceX();
        int y0 = alg.getSourceY();
        int x1 = alg.getProjectionSourceX();
        int y1 = alg.getProjectionSourceY();

        if (shouldRenderLine(x0, y0, x1, y1)) {
            x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
            y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
            x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
            y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

            if (is3D) {
                if (assistDriving) { //truoc day la !stopGPSThread
                    /*
                     * Rotation
                     */
                    Point point0 = new Point(x0, y0);
                    Point point1 = new Point(x1, y1);
                    point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                    point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                    x0 = point0.getX();
                    y0 = point0.getY();
                    x1 = point1.getX();
                    y1 = point1.getY();
                }
                drawLine3D(g, x0, y0, x1, y1, width);
            } else {
                drawLine(g, x0, y0, x1, y1, width);
            }

            //g.fillArc(x1 - 5, y1 - 5, 10, 10, 0, 360);
        }

        // Draw from destination to projection
        x0 = alg.getDestinationX();
        y0 = alg.getDestinationY();
        x1 = alg.getProjectionDestinationX();
        y1 = alg.getProjectionDestinationY();

        if (shouldRenderLine(x0, y0, x1, y1)) {
            x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
            y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
            x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
            y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

            if (is3D) {
                if (assistDriving) { //truoc day la !stopGPSThread
                    /*
                     * Rotation
                     */
                    Point point0 = new Point(x0, y0);
                    Point point1 = new Point(x1, y1);
                    point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                    point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                    x0 = point0.getX();
                    y0 = point0.getY();
                    x1 = point1.getX();
                    y1 = point1.getY();
                }

                drawLine3D(g, x0, y0, x1, y1, width);
            } else {
                drawLine(g, x0, y0, x1, y1, width);
            }

            //g.fillArc(x1 - 5, y1 - 5, 10, 10, 0, 360);
        }

        /*
         * Xet rieng truong hop diem dau va diem cuoi nam cung segment
         */
        if (alg.getSourceClosestSegmentId() == alg.getDestinationClosestSegmentId()) {
            Segment segment = segments[alg.getSourceClosestSegmentId()];
            int bottom = alg.getSourceClosestPointIndex();
            int top = alg.getDestinationClosestPointIndex();

            System.out.println("BOTTOM = " + bottom);
            System.out.println("TOP = " + top);

            if (bottom == top) {
                /*
                 * Khi chung diem gan nhat tren segment thi diem gan nhat nay khong the nam giua 2 diem chieu
                 */
                x0 = alg.getProjectionSourceX();
                y0 = alg.getProjectionSourceY();
                x1 = alg.getProjectionDestinationX();
                y1 = alg.getProjectionDestinationY();
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = getXMap2Screen(x0);
                    y0 = getYMap2Screen(y0);
                    x1 = getXMap2Screen(x1);
                    y1 = getYMap2Screen(y1);
                    if (is3D) {
                        if (assistDriving) { // truoc day la !stopGPSThread
                            /*
                             * Rotation
                             */
                            Point point0 = new Point(x0, y0);
                            Point point1 = new Point(x1, y1);
                            point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                            point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                            x0 = point0.getX();
                            y0 = point0.getY();
                            x1 = point1.getX();
                            y1 = point1.getY();
                        }
                        drawLine3D(g, x0, y0, x1, y1, width);
                    } else {
                        drawLine(g, x0, y0, x1, y1, width);
                    }
                }
            } else {

                if (bottom > top) {
                    int temp = top;
                    top = bottom;
                    bottom = temp;
                }

                bottom++;

                for (int i = bottom; i < top; i++) {
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                    x1 = segment.getX(i + 1);
                    y1 = segment.getY(i + 1);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                }

                x0 = alg.getProjectionSourceX();
                y0 = alg.getProjectionSourceY();
                x1 = segment.getX(bottom);
                y1 = segment.getY(bottom);
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = getXMap2Screen(x0);
                    y0 = getYMap2Screen(y0);
                    x1 = getXMap2Screen(x1);
                    y1 = getYMap2Screen(y1);
                    if (is3D) {

                        if (assistDriving) { //truoc day la !stopGPSThread
                            /*
                             * Rotation
                             */
                            Point point0 = new Point(x0, y0);
                            Point point1 = new Point(x1, y1);
                            point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                            point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                            x0 = point0.getX();
                            y0 = point0.getY();
                            x1 = point1.getX();
                            y1 = point1.getY();
                        }
                        drawLine3D(g, x0, y0, x1, y1, width);
                    } else {
                        drawLine(g, x0, y0, x1, y1, width);
                    }
                }

                x0 = alg.getProjectionDestinationX();
                y0 = alg.getProjectionDestinationY();
                x1 = segment.getX(top);
                y1 = segment.getY(top);
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = getXMap2Screen(x0);
                    y0 = getYMap2Screen(y0);
                    x1 = getXMap2Screen(x1);
                    y1 = getYMap2Screen(y1);
                    if (is3D) {

                        if (assistDriving) { //truoc day la !stopGPSThread
                            /*
                             * Rotation
                             */
                            Point point0 = new Point(x0, y0);
                            Point point1 = new Point(x1, y1);
                            point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                            point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                            x0 = point0.getX();
                            y0 = point0.getY();
                            x1 = point1.getX();
                            y1 = point1.getY();
                        }
                        drawLine3D(g, x0, y0, x1, y1, width);
                    } else {
                        drawLine(g, x0, y0, x1, y1, width);
                    }
                }
            }
        } else {
            /*
             * Ve cac segment o giua
             */
            for (int i = 1; i < alg.getSegmentTrace().size() - 1; i++) {
                Segment segment = (Segment) alg.getSegmentTrace().elementAt(i);
                int maxX = segment.getMaxX();
                int maxY = segment.getMaxY();
                int minX = segment.getMinX();
                int minY = segment.getMinY();
                if (Util.isIntersecting(minX, minY, maxX, maxY)) {
                    drawSegmentInRoute(g, segment, width);
                }
            }

            // Draw from projection to source crossroads
            x1 = alg.getSourceCrossroads().getX();
            y1 = alg.getSourceCrossroads().getY();
            //g.fillArc(getXMap2Screen(x1) - 5, getYMap2Screen(y1) - 5, 10, 10, 0, 360);
            x0 = alg.getProjectionSourceX();
            y0 = alg.getProjectionSourceY();

            Segment segment = segments[alg.getSourceClosestSegmentId()];
            //g.fillArc(segment.getX(alg.getSourceClosestPointIndex()) - 5, segment.getY(alg.getSourceClosestPointIndex()) - 5, 10, 10, 0, 360);

            if (alg.getDirectionTowardSource() == 1) {
                int i = alg.getSourceClosestPointIndex();
                for (; i < segment.getNumberOfPoints(); i++) {
                    x1 = segment.getX(i);
                    y1 = segment.getY(i);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                }
            } else if (alg.getDirectionTowardSource() == -1) {
                int i = alg.getSourceClosestPointIndex();
                for (; i > -1; i--) {
                    x1 = segment.getX(i);
                    y1 = segment.getY(i);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                }
            }

            // Draw from projection to destination crossroads
            x1 = alg.getDestinationCrossroads().getX();
            y1 = alg.getDestinationCrossroads().getY();
            //g.fillArc(getXMap2Screen(x1) - 5, getYMap2Screen(y1) - 5, 10, 10, 0, 360);
            x0 = alg.getProjectionDestinationX();
            y0 = alg.getProjectionDestinationY();

            segment = MapCanvas.segments[alg.getDestinationClosestSegmentId()];
            //g.fillArc(segment.getX(alg.getDestinationClosestPointIndex()) - 5, segment.getY(alg.getDestinationClosestPointIndex()) - 5, 10, 10, 0, 360);

            if (alg.getDirectionTowardDestination() == 1) {
                int i = alg.getDestinationClosestPointIndex();
                for (; i < segment.getNumberOfPoints(); i++) {
                    x1 = segment.getX(i);
                    y1 = segment.getY(i);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                }
            } else if (alg.getDirectionTowardDestination() == -1) {
                int i = alg.getDestinationClosestPointIndex();
                for (; i > -1; i--) {
                    x1 = segment.getX(i);
                    y1 = segment.getY(i);
                    if (shouldRenderLine(x0, y0, x1, y1)) {
                        x0 = getXMap2Screen(x0);
                        y0 = getYMap2Screen(y0);
                        x1 = getXMap2Screen(x1);
                        y1 = getYMap2Screen(y1);
                        if (is3D) {
                            if (assistDriving) { //truoc day la !stopGPSThread
                                /*
                                 * Rotation
                                 */
                                Point point0 = new Point(x0, y0);
                                Point point1 = new Point(x1, y1);
                                point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                                point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                                x0 = point0.getX();
                                y0 = point0.getY();
                                x1 = point1.getX();
                                y1 = point1.getY();
                            }
                            drawLine3D(g, x0, y0, x1, y1, width);
                        } else {
                            drawLine(g, x0, y0, x1, y1, width);
                        }
                    }
                    x0 = segment.getX(i);
                    y0 = segment.getY(i);
                }
            }
        }
        if (alg.getSourceClosestSegmentId() != alg.getDestinationClosestSegmentId()) {
            /*
             * Ve cac mui ten chi huong di
             */
            for (int i = alg.getCrossroadsTrace().size() - 2; i > 1; i--) {
                Segment segment = segments[RoutingAlgorithm.getAdjacentSegmentId2(
                        ((Crossroads) alg.getCrossroadsTrace().elementAt(i)).getId(),
                        ((Crossroads) alg.getCrossroadsTrace().elementAt(i - 1)).getId())];
                Crossroads crossroads = (Crossroads) alg.getCrossroadsTrace().elementAt(i);
                if (crossroads.getX() == segment.getX(0) && crossroads.getY() == segment.getY(0)) {
                    x0 = segment.getX(0) & 0xFFFF;
                    y0 = segment.getY(0) & 0xFFFF;
                    x1 = segment.getX(1) & 0xFFFF;
                    y1 = segment.getY(1) & 0xFFFF;
                } else {
                    x0 = segment.getX(segment.getNumberOfPoints() - 1) & 0xFFFF;
                    y0 = segment.getY(segment.getNumberOfPoints() - 1) & 0xFFFF;
                    x1 = segment.getX(segment.getNumberOfPoints() - 2) & 0xFFFF;
                    y1 = segment.getY(segment.getNumberOfPoints() - 2) & 0xFFFF;
                }

                if (isInside(x0, y0) && isInside(x1, y1)) {
                    x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
                    y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
                    x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
                    y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

                    if (assistDriving) { //truoc day la !stopGPSThread
                        /*
                         * Rotation
                         */
                        Point point0 = new Point(x0, y0);
                        Point point1 = new Point(x1, y1);
                        point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                        point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                        x0 = point0.getX();
                        y0 = point0.getY();
                        x1 = point1.getX();
                        y1 = point1.getY();
                    }
                    if (is3D) {
                        Point point0 = new Point(x0, y0);
                        Point point1 = new Point(x1, y1);
                        warper.warpPoint(point0);
                        warper.warpPoint(point1);
                        x0 = point0.getX();
                        y0 = point0.getY();
                        x1 = point1.getX();
                        y1 = point1.getY();
                    }
                    int color = g.getColor();
                    g.setColor(244, 164, 96);
                    DirectionArrowDrawer.draw(g, x0, y0, x1, y1, 5);
                    g.setColor(color);
                }
            }
        }
    }

    public void drawSegmentInRoute(Graphics g, Segment segment, int width) {
        for (int i = 0; i < segment.getNumberOfPoints() - 1; i++) {
            int x0 = segment.getX(i) & 0xFFFF;
            int y0 = segment.getY(i) & 0xFFFF;
            int x1 = segment.getX(i + 1) & 0xFFFF;
            int y1 = segment.getY(i + 1) & 0xFFFF;

            if (shouldRenderLine(x0, y0, x1, y1)) {
                x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
                y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
                x1 = (x1 - MinX) * screenWidth / (MaxY - MinY);
                y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

                if (assistDriving && is3D) { //truoc day la !stopGPSThread && is3D
                    /*
                     * Rotation
                     */
                    Point point0 = new Point(x0, y0);
                    Point point1 = new Point(x1, y1);
                    point0 = MapRotation.rotate(point0, currentPositionOnScreen, -rotationAngle);
                    point1 = MapRotation.rotate(point1, currentPositionOnScreen, -rotationAngle);
                    x0 = point0.getX();
                    y0 = point0.getY();
                    x1 = point1.getX();
                    y1 = point1.getY();
                }

                /*
                 * Clipping
                 */
                if (x0 < 0) {
                    if (x1 < 0) {
                        continue;
                    }
                    y0 += (y1 - y0) * (-x0) / (x1 - x0);
                    x0 = 0;
                } else if (x0 > screenWidth) {
                    if (x1 > screenWidth) {
                        continue;
                    }
                    y0 += (y1 - y0) * (screenWidth - x0) / (x1 - x0);
                    x0 = screenWidth;
                }
                if (x1 < 0) {
                    y1 += (y0 - y1) * (-x1) / (x0 - x1);
                    x1 = 0;
                } else if (x1 > screenWidth) {
                    y1 += (y0 - y1) * (screenWidth - x1) / (x0 - x1);
                    x1 = screenWidth;
                }
                if (y0 < 0) {
                    if (y1 < 0) {
                        continue;
                    }
                    x0 += (x1 - x0) * (-y0) / (y1 - y0);
                    y0 = 0;
                } else if (y0 > screenHeight) {
                    if (y1 > screenHeight) {
                        continue;
                    }
                    x0 += (x1 - x0) * (screenHeight - y0) / (y1 - y0);
                    y0 = screenHeight;
                }
                if (y1 < 0) {
                    x1 += (x0 - x1) * (-y1) / (y0 - y1);
                    y1 = 0;
                } else if (y1 > screenHeight) {
                    x1 += (x0 - x1) * (screenHeight - y1) / (y0 - y1);
                    y1 = screenHeight;
                }

                if (is3D) {
                    drawLine3D(g, x0, y0, x1, y1, width);
                } else {
                    drawLine(g, x0, y0, x1, y1, width);
                }
            }
        }
    }

    public void shift(int dx, int dy) {
        /*
        Point point0 = null;
        Point point1 = null;
        for(int angle = 0; angle < rotationAngle; angle ++) {
        point0 = MapRotation.rotateClockwise(-150, -150);
        point1 = MapRotation.rotateClockwise(150, 150);
        }
        MinX = point0.getX() + (MinX + 150);
        MinY = point0.getY() + (MinY + 150);
        MaxX = point1.getX() + (MinX + 150);
        MaxY = point1.getY() + (MinY + 150);
         */
        MinX += dx;
        MinY += dy;
        MaxX += dx;
        MaxY += dy;
    }

    public boolean isInside(int x, int y) {
        if (x > MinX && x < MaxX
                && y > MinY && y < MaxY) {
            return true;
        }
        return false;
    }

    public void drawConstructionSites(Graphics g) {
        int minX, minY, maxX, maxY, x, y;
        Segment segment;
        for (int i = 0; i < constructionSiteSegmentIds.size(); i++) {
            segment = segments[((Integer) constructionSiteSegmentIds.elementAt(i)).intValue()];
            maxX = segment.getMaxX();
            maxY = segment.getMaxY();
            minX = segment.getMinX();
            minY = segment.getMinY();
            if (Util.isIntersecting(minX, minY, maxX, maxY)) {
                x = segment.getX(segment.getNumberOfPoints() / 2 - 1) + (segment.getX(segment.getNumberOfPoints() / 2) - segment.getX(segment.getNumberOfPoints() / 2 - 1)) / 2;
                y = segment.getY(segment.getNumberOfPoints() / 2 - 1) + (segment.getY(segment.getNumberOfPoints() / 2) - segment.getY(segment.getNumberOfPoints() / 2 - 1)) / 2;
                if (isInside(x, y)) {
                    placeSprite.setFrame(25);
                    placeSprite.setPosition(getXMap2Screen(x), getYMap2Screen(y));
                    placeSprite.paint(g);
                }
            }
        }
    }

    public void drawRegion(Graphics g, Region region) {
        Point point = null;
        //Can clipping truoc khi ve
        if (region.getType() == 20) //g.setColor(0, 205, 102);	// SpringGreen3
        {
            g.setColor(205, 175, 149);
        } // PeachPuff3
        else if (region.getType() == 41) {
            g.setColor(102, 205, 170);
        } // Aquamarine3
        else {
            return;
        }
        int[] x = new int[region.getNumberOfPoints() * 2];
        int[] y = new int[region.getNumberOfPoints() * 2];
        int[] clippedX = new int[x.length];
        int[] clippedY = new int[x.length];
        for (int i = 0; i < region.getNumberOfPoints(); i++) {
            x[i] = (region.getX(i) - MinX) * screenWidth / (MaxX - MinX);
            y[i] = (region.getY(i) - MinY) * screenHeight / (MaxY - MinY);

            if (is3D && !stopGPSThread) {
                point = new Point(x[i], y[i]);
                point = MapRotation.rotate(point, -rotationAngle);
                x[i] = point.getX();
                y[i] = point.getY();
            }
        }

        PolygonClipper.clip_x_min = 0;
        PolygonClipper.clip_y_min = 0;
        PolygonClipper.clip_x_max = screenWidth;
        PolygonClipper.clip_y_max = screenHeight;

        int c = PolygonClipper.SutherlandHodgmanPolygonClip(region.getNumberOfPoints(), x,
                y, // input verts
                clippedX, clippedY, // output verts
                0);

        if (c > 0) {
            c = PolygonClipper.SutherlandHodgmanPolygonClip(c, clippedX, clippedY, // input														// verts
                    x, y, // output verts
                    1);
            if (c > 0) {
                c = PolygonClipper.SutherlandHodgmanPolygonClip(c, x, y, // input										// verts
                        clippedX, clippedY, // output verts
                        2);
                if (c > 0) {
                    c = PolygonClipper.SutherlandHodgmanPolygonClip(c, clippedX,
                            clippedY, // input verts
                            x, y, // output verts
                            3);
                }
            }
        }

        if (c > 2) {
            clippedX = new int[c];
            clippedY = new int[c];
            for (int i = 0; i < c; i++) {
                clippedX[i] = x[i];
                clippedY[i] = y[i];
            }

            if (is3D) {
                warper.warpPoints(clippedX, clippedY);
            }
            PolygonUtil.fillPolygon(g, clippedX, clippedY);
        }

        /*
        g.setColor(0, 0, 255);
        int i = 0;
        for(; i < xPoints.length - 1; i++) {
        g.drawLine(xPoints[i], yPoints[i], xPoints[i + 1], yPoints[i + 1]);
        System.out.println(xPoints[i] + " " + yPoints[i]);
        }
        g.drawLine(xPoints[i], yPoints[i], xPoints[0], yPoints[0]);
        System.out.println(xPoints[i] + " " + yPoints[i]);
         */
    }

    public int getFrameIdFromPlaceType(int type) {
        int id = 0;
        switch (type) {
            case 1:
                id = 1;
                break;
            case 2:
                id = 2;
                break;
            case 9:
                id = 6;
                break;
            case 25:
                id = 4;
                break;
            case 33:
                id = 14;
                break;
            case 50:
                id = 0;
                break;
            default:
                break;
        }
        return id;
    }

    public void drawPOI(Graphics g, SimpleLocation location) {
        /*
         * Tam thoi khong ve lo cot o day do da ve ngay truoc do
         * bang cach doc trong constructionSiteSegmentIds
         */
        if (location.getType() == LayerConfig.LAYER_CONSTRUCTIONSITE) {
            return;
        }
        int x = location.getX();
        int y = location.getY();
        if (isInside(x, y)) {
            double d = Util.calculateDistancePoint2Point(cursorCenterX, cursorCenterY, location.getX(), location.getY());
            if (d < EPSILON) {
                placeNearCursor = Util.decodeCharacters(location.getName());
            }

            placeSprite.setFrame(getFrameIdFromPlaceType(location.getType()));
            x = (x - MinX) * screenWidth / (MaxX - MinX);
            y = (y - MinY) * screenHeight / (MaxY - MinY);
            if (is3D) {
                Point point = new Point(x, y);
                if (!stopGPSThread) {
                    point = MapRotation.rotate(point, -rotationAngle);
                }
                if (warper.warpPoint(point) != 0) {
                    x = point.getX();
                    y = point.getY();
                    placeSprite.setPosition(x, y);
                    placeSprite.paint(g);
                }
                point = null;
            } else {
                placeSprite.setPosition(x, y);
                placeSprite.paint(g);
            }
        }

    }

    // Draw your current position
    public void drawCurrentPosition(Graphics g) {
        int x = (currentX - MinX) * screenWidth / (MaxX - MinX);
        int y = (currentY - MinY) * screenHeight / (MaxY - MinY);
        //System.out.println("X = " + x);
        //System.out.println("Y = " + y);
        vanSprite.setPosition(x, y);
        if (is3D) {
            Point point = new Point(vanSprite.getX(), vanSprite.getY());
            warper.warpPoint(point);
            vanSprite.setPosition(point.getX(), point.getY());
        }
        vanSprite.paint(g);
        //flushGraphics();
    }

    public void drawCrossroads(Graphics g, Crossroads crossroads) {
        int x = crossroads.getX() & 0xFFFF;
        int y = crossroads.getY() & 0xFFFF;
        if (isInside(x, y)) {
            x = (x - MinX) * screenWidth / (MaxX - MinX);
            y = (y - MinY) * screenHeight / (MaxY - MinY);

            g.setColor(255, 255, 255);
            if (crossroads.getSegments().length > 4) {
                switch (zoomLevel) {
                    case 3:
                        g.fillArc(x - 8, y - 8, 16, 16, 0, 360);
                        break;
                    case 4:
                        //g.setColor(95, 158, 160);
                        g.fillArc(x - 16, y - 16, 32, 32, 0, 360);
                        break;
                    case 5:
                        //g.setColor(238, 221, 130);
                        g.fillArc(x - 20, y - 20, 40, 40, 0, 360);
                        break;
                    default:
                        break;
                }
            }
        }

    }

    public void drawCrossroads3D(Graphics g, Crossroads crossroads) {
        int x = crossroads.getX() & 0xFFFF;
        int y = crossroads.getY() & 0xFFFF;
        if (isInside(x, y)) {
            x = (x - MinX) * screenWidth / (MaxX - MinX);
            y = (y - MinY) * screenHeight / (MaxY - MinY);

            /*
             * 3D moi xoay ban do
             */
            if (!stopGPSThread) {
                Point point = new Point(x, y);
                point = MapRotation.rotate(point, currentPositionOnScreen, -rotationAngle);
                x = point.getX();
                y = point.getY();
                point = null;
            }

            g.setColor(255, 255, 255);
            if (crossroads.getSegments().length > 4) {
                switch (zoomLevel) {
                    case 3:
                        fillArc3D(g, x - 12, y - 12, 24, 24, 0, 360);
                        break;
                    case 4:
                        //g.setColor(95, 158, 160);
                        fillArc3D(g, x - 20, y - 20, 40, 40, 0, 360);
                        break;
                    case 5:
                        //g.setColor(238, 221, 130);
                        fillArc3D(g, x - 24, y - 24, 48, 48, 0, 360);
                        break;
                    default:
                        break;
                }
            }
        }

    }

    public void drawString(Graphics g, String str, int x, int y) {
        if (str != null) {
            //g.drawString(str, x, y, Graphics.LEFT | Graphics.BOTTOM);
            Util.drawText(g, str, x, y, 0x00000000, 0x000000FF);

        }
    }

    private void zoomOut(int zoom) {
        MinX -= zoom;
        MinY -= zoom;
        MaxX += zoom;
        MaxY += zoom;
        DX += 20;
        DY = DX;
        zoomLevel--;
    }

    private void zoomIn(int zoom) {
        MinX += zoom;
        MinY += zoom;
        MaxX -= zoom;
        MaxY -= zoom;
        DX -= 20;
        DY = DX;
        zoomLevel++;
    }

    public void testLBS() {
        //#ifdef GPS
//# 		/*
//# 		try {
//#
//# 				Criteria criteria = new Criteria();
//# 				criteria.setCostAllowed(true);
//# 				criteria.setPreferredPowerConsumption(Criteria.NO_REQUIREMENT);
//#
//# 				// Get a location provider based on the aforementioned criteria.
//# 				LocationProvider provider = LocationProvider.getInstance(criteria);
//#
//# 				// Try to fetch the current location (using a 3 minute timeout).
//# 				Location location = provider.getLocation(180);
//#
//# 				// Get the coordinates of the current location.
//# 				Coordinates coordinates = location.getQualifiedCoordinates();
//#
//# 				if (coordinates  != null) {
//# 				    // Get the latitude and longitude of the coordinates.
//# 				    double latitude = coordinates.getLatitude();
//# 				    double longitude = coordinates.getLongitude();
//#
//# 				    Point point =Util.createPoint(longitude, latitude);
//# 				    currentX = point.getX() & 0xFFFF;
//# 				    currentY = point.getY() & 0xFFFF;
//#
//# 				    System.out.println("LAT = " + latitude);
//# 				    System.out.println("LON = " + longitude);
//# 				    if(!isInside(currentX, currentY)) {
//# 				    	Util.centerScreen(currentX, currentY);
//# 				    }
//#
//# 					repaint();
//# 				} else {
//# 					// You didn't get any coordinates.
//# 				}
//#
//# 		}
//# 		catch(Exception exception){
//# 			exception.printStackTrace();
//# 		}
//# 		*/
        //#endif
    }

    public void searchGPS(int time) {

        MobileGPS.init();
        MobileGPS.searchGPS();

        //midlet.showSplashCanvas(midlet.gpsConnectionList);

        try {
            Thread.sleep(time);
        } catch (Exception exception) {
            exception.printStackTrace();
        }

        String[] deviceNames = null;
        if (MobileGPS.mBluelet.isInquiryCompleted()) {

            Vector devices = MobileGPS.mBluelet.getDevices();
            deviceNames = new String[devices.size()];

            try {
                for (int i = 0; i < devices.size(); i++) {
                    RemoteDevice device = (RemoteDevice) devices.elementAt(i);
                    deviceNames[i] = device.getFriendlyName(false);
                }
            } catch (IOException exception) {
                exception.printStackTrace();
            }
        }
        MobileGPS.stop();

        //#ifdef GPS
//# 		String[] newDeviceNames = new String[deviceNames.length];
//# 		System.arraycopy(deviceNames, 0, newDeviceNames, 0, deviceNames.length);
//# 		newDeviceNames[deviceNames.length] = "Internal GPS Receiver";
//# 		deviceNames = newDeviceNames;
        //#endif
        midlet.showGPSConnectionList(deviceNames);

    }

    public void startGPS(int selectedDeviceId) {
        if (selectedDeviceId >= MobileGPS.mBluelet.getDevices().size()) {//internal GPS receiver
            stopGPSThread = false;
            new Thread() {

                public void run() {
                    testLBS();
                }
            }.start();
            return;
        }
        MobileGPS.connectGPS(selectedDeviceId);

        try {
            Thread.sleep(10000);
        } catch (Exception exception) {
            exception.printStackTrace();
        }

        if (MobileGPS.mBluelet.getServices().size() > 0) {
            /*
             * Khong getGPSInformation thi khong co sReferences --> ket noi voi may tinh #-o
             * sReferences ghi vao RMS :-??
             * Tam thoi dung cai nay de lay sReferences (khong co khong duoc)
             * Se sua lai sau
             *
             * new MobileGPS --> initGPSTrack --> tao RecordStore chua references (chua co gi nen chua thong tin rac)
             * getGPSInformation --> ghi thong tin ket noi bluetooth (chua trong 1 references) vao RecordStore (trung recordStoreId voi RS o tren --> ghi de)
             * runGPS --> open GPS --> lay thong tin tu RMS (RS o tren) bo vao references --> chay (sai references khong chay)
             * Khi luu references deu luu chung 1 RS (chung recordStoreId)
             */
            MobileGPS.getGPSInformation();
            try {
                stopGPSThread = false;
                new Thread() {

                    public void run() {
                        runGPS();
                    }
                }.start();
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        } else {
            // Do something to alert
        }
    }

    public void runGPS() {
        long start = System.currentTimeMillis();

        drawTrack = false;
        int intPoint = 0;
        Point point;
        RSManager.open(Util.GPS_TRACK_RECORDSTORE_NAME);

        //Thread thread = Thread.currentThread();
        earthPosition = null;
        EarthPosition lastEarthPosition = null, lastPointEarthPosition = null;
        Gps gps = MobileGPS.getGps();
        gps.open();

        long currentTime, lastTime = 0;

        try {
            while (!stopGPSThread) {
                currentTime = System.currentTimeMillis();
                if (earthPosition != null) {
                    lastEarthPosition = earthPosition;
                }
                earthPosition = gps.getEarthPosition();
                if (earthPosition != null) {
                    double longitude = Double.parseDouble(earthPosition.getLongitude().toString());
                    double latitude = Double.parseDouble(earthPosition.getLatitude().toString());

                    point = Util.createPoint(longitude, latitude);

                    currentX = point.getX() & 0xFFFF;
                    currentY = point.getY() & 0xFFFF;

                    if (lastEarthPosition != null) {
                        int distance = (int) Double.valueOf(earthPosition.getDistance(lastEarthPosition).toString()).doubleValue();
                        if (distance > 10 && distance < 100) {
                            if (is3D) {
                                rotationAngle = calAngle(lastEarthPosition, earthPosition);
                            } else {
                                rotationAngle = 0;
                            }



                            if (assistDriving) {
                                if (alg.getSourceCrossroads() == null) {
                                    alg.setSource(point.getX() & 0xFFFF, point.getY() & 0xFFFF);
                                    moveToCurrentPosition = false;
                                }
                            }
                        }
                        if (currentTime - lastTime >= Util.SERVER_DELAY_TIME && Util.UPDATE_POSITION) {
                            //String str = "id=" + Util.DEVICE_ID + "&" + "lat=" + earthPosition.getLatitude().toString() + "&lng=" + earthPosition.getLongitude().toString()/* + "&speed=" + gps.getSpeed()*/;
                            String str = "Id=" + Util.DEVICE_ID + "&" + "lat=" + earthPosition.getLatitude().toString() + "&lng=" + earthPosition.getLongitude().toString() + "&speed=" + gps.getSpeed();
                            System.out.println(str);
                            sendDataToServer(Util.UPDATE_POSITION_URL, str);

                            lastTime = currentTime;

                            // Set X
                            intPoint = ((currentX & 0xFFFF) << 16) | (intPoint & 0xFFFF);
                            // Set Y
                            intPoint = (intPoint & 0xFFFF0000) | (currentY & 0xFFFF);
                            System.out.println(intPoint);
                            track.addElement(new Integer(intPoint));

                        }
                    }

                    if (moveToCurrentPosition) {
                        if (is3D) {
                            //Util.centerScreen(currentX, currentY);
                            int d = MaxX - MinX;
                            MinX = currentX - d / 2;
                            MinY = currentY - d + 20;
                            MaxX = MinX + d;
                            MaxY = MinY + d;
                        } else {
                            if (!isInside(currentX, currentY)) {
                                int d = MaxX - MinX;
                                MinX = currentX - 20;
                                MinY = currentY - 20;
                                MaxX = MinX + d;
                                MaxY = MinY + d;
                            }
                        }
                        repaint();
                    }
                }
            }
            if (stopGPSThread) {
                //thread.interrupt();
                gps.close();
                //stopGPSThread = false;
                System.out.println(track.size());

                if (track.size() > 0) {
                    RSManager.open(Util.GPS_TRACK_RECORDSTORE_NAME);
                    RSManager.saveTrack(new Date().toString(), track);
                    RSManager.close();
                    track.removeAllElements();
                }

            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    private int getSegmentWidth(byte segmentType, byte zoomLevel) {
        return segmentWidths[zoomLevel * numSegmentTypes + segmentType];
    }

    /*
     * LOI: ki tu trong ten duoc nhay tum lum khi rai
     * NGUYEN NHAN: chon x nho hon lam diem bat dau ve
     * KET QUA: duong gap khuc (x tang giam bat thuong) la thua, chi ve tren duong tang dan hay giam dan
     * TINH TRANG: chua sua
     * DE XUAT: chinh lai du lieu
     */
    public void drawStreetName2(Graphics g, Segment segment) {
        byte[] name = paths[segment.getPathId()].getName();
        int x0, y0, x1, y1;
        int start = 0;

        if (segment.getX(0) < segment.getX(segment.getNumberOfPoints() - 1)) {
            for (int i = 0; i < segment.getNumberOfPoints() - 1; i++) {
                x0 = segment.getX(i) & 0xFFFF;
                y0 = segment.getY(i) & 0xFFFF;
                x1 = segment.getX(i + 1) & 0xFFFF;
                y1 = segment.getY(i + 1) & 0xFFFF;
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
                    y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
                    x1 = (x1 - MinX) * screenWidth / (MaxX - MinX);
                    y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

                    if (is3D) {
                        Point point = new Point(x1, y1);
                        if (warper.warpPoint(point) != 0) {
                            int x = point.getX();
                            int y = point.getY();
                            g.setColor(255, 0, 0);
                            g.fillArc(x - 2, y - 2, 4, 4, 0, 360);
                            g.setColor(0, 0, 0);
                            drawString(g, Util.decodeCharacters(name), x + 5, y + 5);
                        }
                        break;
                    } else {
                        if (x1 < x0) {
                            start = stringDrawer.draw(g, name, x1, y1, x0, y0, start);
                        } else {
                            start = stringDrawer.draw(g, name, x0, y0, x1, y1, start);
                        }
                        if (start == name.length) {
                            break;
                        }
                    }
                }
            }

        } else {

            for (int i = segment.getNumberOfPoints() - 1; i > 0; i--) {
                x0 = segment.getX(i) & 0xFFFF;
                y0 = segment.getY(i) & 0xFFFF;
                x1 = segment.getX(i - 1) & 0xFFFF;
                y1 = segment.getY(i - 1) & 0xFFFF;
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
                    y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
                    x1 = (x1 - MinX) * screenWidth / (MaxX - MinX);
                    y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

                    if (is3D) {
                        Point point = new Point(x1, y1);
                        if (warper.warpPoint(point) != 0) {
                            int x = point.getX();
                            int y = point.getY();
                            g.setColor(255, 0, 0);
                            g.fillArc(x - 2, y - 2, 4, 4, 0, 360);
                            g.setColor(0, 0, 0);
                            drawString(g, Util.decodeCharacters(name), x + 5, y + 5);
                        }
                        break;
                    } else {
                        if (x1 < x0) {
                            start = stringDrawer.draw(g, name, x1, y1, x0, y0, start);
                        } else {
                            start = stringDrawer.draw(g, name, x0, y0, x1, y1, start);
                        }
                        if (start == name.length) {
                            break;
                        }
                    }
                }
            }
        }
    }

    public boolean sufficientLength(Segment segment) {
        Path path = paths[segment.getPathId()];
        byte[] name = path.getName();

        int x0, y0, x1, y1;
        int start = 0;
        if (segment.getX(0) < segment.getX(segment.getNumberOfPoints() - 1)) {
            for (int i = 0; i < segment.getNumberOfPoints() - 1; i++) {
                x0 = segment.getX(i) & 0xFFFF;
                y0 = segment.getY(i) & 0xFFFF;
                x1 = segment.getX(i + 1) & 0xFFFF;
                y1 = segment.getY(i + 1) & 0xFFFF;
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
                    y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
                    x1 = (x1 - MinX) * screenWidth / (MaxX - MinX);
                    y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

                    if (x1 < x0) {
                        start = stringDrawer.check(name, x1, y1, x0, y0, start);
                    } else {
                        start = stringDrawer.check(name, x0, y0, x1, y1, start);
                    }
                    if (start == name.length) {
                        return true;
                    }

                }
            }
        } else {
            for (int i = segment.getNumberOfPoints() - 1; i > 0; i--) {
                x0 = segment.getX(i) & 0xFFFF;
                y0 = segment.getY(i) & 0xFFFF;
                x1 = segment.getX(i - 1) & 0xFFFF;
                y1 = segment.getY(i - 1) & 0xFFFF;
                if (shouldRenderLine(x0, y0, x1, y1)) {
                    x0 = (x0 - MinX) * screenWidth / (MaxX - MinX);
                    y0 = (y0 - MinY) * screenHeight / (MaxY - MinY);
                    x1 = (x1 - MinX) * screenWidth / (MaxX - MinX);
                    y1 = (y1 - MinY) * screenHeight / (MaxY - MinY);

                    if (x1 < x0) {
                        start = stringDrawer.check(name, x1, y1, x0, y0, start);
                    } else {
                        start = stringDrawer.check(name, x0, y0, x1, y1, start);
                    }
                    if (start == name.length) {
                        return true;
                    }

                }
            }
        }
        return false;
    }

    public static int getXScreen2Map(int x) {
        return x * (MaxX - MinX) / screenWidth + MinX;
    }

    public static int getYScreen2Map(int y) {
        return y * (MaxY - MinY) / screenHeight + MinY;
    }

    public static int getXMap2Screen(int x) {
        return (x - MinX) * screenWidth / (MaxX - MinX);
    }

    public static int getYMap2Screen(int y) {
        return (y - MinY) * screenHeight / (MaxY - MinY);
    }

    public void moveOnRoute(Vector route) {
        try {
            for (int i = 0; i < route.size(); i++) {
                Segment segment = (Segment) route.elementAt(i);
                for (int j = 0; j < segment.getNumberOfPoints(); j++) {
                    Util.centerScreen(segment.getX(j), segment.getY(j));
                    int x = getXMap2Screen(segment.getX(j));
                    int y = getXMap2Screen(segment.getY(j));
                    pointer.setPosition(x, y);
                    repaint();
                    Thread.sleep(500);
                }
            }
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        }
    }

    public int HttpLoadCompleted(byte[] data, int errorCode, MHttpConnItem item) {
        if (data == null) {
            System.out.println("NULL" + errorCode);
        } else {
            String str = new String(data);
            //MapDrawer.showAlert(str);
            System.out.println(str);
        }
        return 0;
    }
    private MHttpConnection conn;

    private void sendDataToServer(String url, String data) {
        System.out.println(url);
        MHttpConnItem item = new MHttpConnItem(0, this, url, false, true, data.getBytes());
        if (conn == null) {
            conn = new MHttpConnection();
            conn.addItem(item);
            conn.start();
        } else {
            conn.addItem(item);
        }
    }

    private int calAngle(EarthPosition pos0, EarthPosition pos1) {
        Point point0 = Util.createPoint(Double.valueOf(pos0.getLongitude().toString()).doubleValue(), Double.valueOf(pos0.getLatitude().toString()).doubleValue());
        Point point1 = Util.createPoint(Double.valueOf(pos1.getLongitude().toString()).doubleValue(), Double.valueOf(pos1.getLatitude().toString()).doubleValue());
        int vx = point1.getX() - point0.getX();
        int vy = point1.getY() - point0.getY();
        System.out.println("VECTOR = " + vx + " " + vy);
        // tinh goc (vx, vy) va (0, -1)
        int ret = (int) ((-vy) * 1000.0 / Math.sqrt(vx * vx + vy * vy));
        int angle = 180;
        if (ret > 985) {
            angle = 0;
        } else if (ret > 940) {
            angle = 10;
        } else if (ret > 867) {
            angle = 20;
        } else if (ret > 767) {
            angle = 30;
        } else if (ret > 643) {
            angle = 40;
        } else if (ret > 500) {
            angle = 50;
        } else if (ret > 343) {
            angle = 60;
        } else if (ret > 174) {
            angle = 70;
        } else if (ret > 0) {
            angle = 80;
        } else if (ret > -173) {
            angle = 90;
        } else if (ret > -342) {
            angle = 100;
        } else if (ret > -342) {
            angle = 100;
        } else if (ret > -500) {
            angle = 110;
        } else if (ret > -642) {
            angle = 120;
        } else if (ret > -766) {
            angle = 130;
        } else if (ret > -866) {
            angle = 140;
        } else if (ret > -939) {
            angle = 150;
        } else if (ret > -984) {
            angle = 160;
        } else if (ret > -1000) {
            angle = 170;
        } else {
            angle = 180;
        }

        /*
         * Xet them dau vy
         * Co le neu vy > 0 và vx < 0 thi cong them 180, thay vi 90
         */
        if (vx < 0) //just for funny test and ... OMG, successful (for only one test)!
        {
            angle += 90;
        }
        return angle;
    }
}
